blob: 210313896004d2efd39484b2aaa52a43138b94d1 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
henrike@webrtc.org28e20752013-07-10 00:45:36 +000011#ifdef HAVE_WEBRTC_VOICE
12
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010013#include "webrtc/media/engine/webrtcvoiceengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
15#include <algorithm>
16#include <cstdio>
ossuc54071d2016-08-17 02:45:41 -070017#include <functional>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018#include <string>
19#include <vector>
20
kjellandera69d9732016-08-31 07:33:05 -070021#include "webrtc/api/call/audio_sink.h"
tfarina5237aaf2015-11-10 23:44:30 -080022#include "webrtc/base/arraysize.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000023#include "webrtc/base/base64.h"
24#include "webrtc/base/byteorder.h"
kwiberg4485ffb2016-04-26 08:14:39 -070025#include "webrtc/base/constructormagic.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000026#include "webrtc/base/helpers.h"
27#include "webrtc/base/logging.h"
solenberg347ec5c2016-09-23 04:21:47 -070028#include "webrtc/base/race_checker.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000029#include "webrtc/base/stringencode.h"
30#include "webrtc/base/stringutils.h"
Peter Boströmca8b4042016-03-08 14:24:13 -080031#include "webrtc/base/trace_event.h"
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080032#include "webrtc/media/base/audiosource.h"
kjellanderf4752772016-03-02 05:42:30 -080033#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080034#include "webrtc/media/base/streamparams.h"
solenberg9a5f032222017-03-15 06:14:12 -070035#include "webrtc/media/engine/adm_helpers.h"
solenberg76377c52017-02-21 00:54:31 -080036#include "webrtc/media/engine/apm_helpers.h"
ossuc54071d2016-08-17 02:45:41 -070037#include "webrtc/media/engine/payload_type_mapper.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010038#include "webrtc/media/engine/webrtcmediaengine.h"
39#include "webrtc/media/engine/webrtcvoe.h"
aleloi10111bc2016-11-17 06:48:48 -080040#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010042#include "webrtc/system_wrappers/include/field_trial.h"
solenberg2100c0b2017-03-01 11:29:29 -080043#include "webrtc/system_wrappers/include/metrics.h"
solenbergbd138382015-11-20 16:08:07 -080044#include "webrtc/system_wrappers/include/trace.h"
solenberg76377c52017-02-21 00:54:31 -080045#include "webrtc/voice_engine/transmit_mixer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047namespace cricket {
solenbergd97ec302015-10-07 01:40:33 -070048namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049
solenbergebb349d2017-03-13 05:46:15 -070050constexpr size_t kMaxUnsignaledRecvStreams = 1;
solenberg2100c0b2017-03-01 11:29:29 -080051
solenbergbd138382015-11-20 16:08:07 -080052const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
53 webrtc::kTraceWarning | webrtc::kTraceError |
54 webrtc::kTraceCritical;
55const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
56 webrtc::kTraceInfo;
57
solenberg971cab02016-06-14 10:02:41 -070058constexpr int kNackRtpHistoryMs = 5000;
minyue@webrtc.org2dc6f312014-10-31 05:33:10 +000059
peah1bcfce52016-08-26 07:16:04 -070060// Check to verify that the define for the intelligibility enhancer is properly
61// set.
62#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
63 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \
64 WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
65#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
66#endif
67
ossu20a4b3f2017-04-27 02:08:52 -070068// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
minyue10cbb462016-11-07 09:29:22 -080069const int kOpusMinBitrateBps = 6000;
ossu20a4b3f2017-04-27 02:08:52 -070070const int kOpusBitrateFbBps = 32000;
deadbeef80346142016-04-27 14:17:10 -070071
wu@webrtc.orgde305012013-10-31 15:40:38 +000072// Default audio dscp value.
73// See http://tools.ietf.org/html/rfc2474 for details.
74// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
solenbergd97ec302015-10-07 01:40:33 -070075const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000076
Fredrik Solenbergb5727682015-12-04 15:22:19 +010077// Constants from voice_engine_defines.h.
78const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
79const int kMaxTelephoneEventCode = 255;
Fredrik Solenbergb5727682015-12-04 15:22:19 +010080
solenberg31642aa2016-03-14 08:00:37 -070081const int kMinPayloadType = 0;
82const int kMaxPayloadType = 127;
83
deadbeef884f5852016-01-15 09:20:04 -080084class ProxySink : public webrtc::AudioSinkInterface {
85 public:
86 ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
87
88 void OnData(const Data& audio) override { sink_->OnData(audio); }
89
90 private:
91 webrtc::AudioSinkInterface* sink_;
92};
93
solenberg0b675462015-10-09 01:37:09 -070094bool ValidateStreamParams(const StreamParams& sp) {
95 if (sp.ssrcs.empty()) {
96 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
97 return false;
98 }
99 if (sp.ssrcs.size() > 1) {
100 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
101 return false;
102 }
103 return true;
104}
105
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106// Dumps an AudioCodec in RFC 2327-ish format.
solenbergd97ec302015-10-07 01:40:33 -0700107std::string ToString(const AudioCodec& codec) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 std::stringstream ss;
ossu20a4b3f2017-04-27 02:08:52 -0700109 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
110 if (!codec.params.empty()) {
111 ss << " {";
112 for (const auto& param : codec.params) {
113 ss << " " << param.first << "=" << param.second;
114 }
115 ss << " }";
116 }
117 ss << " (" << codec.id << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118 return ss.str();
119}
Minyue Li7100dcd2015-03-27 05:05:59 +0100120
solenbergd97ec302015-10-07 01:40:33 -0700121bool IsCodec(const AudioCodec& codec, const char* ref_name) {
Minyue Li7100dcd2015-03-27 05:05:59 +0100122 return (_stricmp(codec.name.c_str(), ref_name) == 0);
123}
124
solenbergd97ec302015-10-07 01:40:33 -0700125bool FindCodec(const std::vector<AudioCodec>& codecs,
solenberg26c8c912015-11-27 04:00:25 -0800126 const AudioCodec& codec,
127 AudioCodec* found_codec) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200128 for (const AudioCodec& c : codecs) {
129 if (c.Matches(codec)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 if (found_codec != NULL) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200131 *found_codec = c;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132 }
133 return true;
134 }
135 }
136 return false;
137}
wu@webrtc.org1d1ffc92013-10-16 18:12:02 +0000138
solenberg0b675462015-10-09 01:37:09 -0700139bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
140 if (codecs.empty()) {
141 return true;
142 }
143 std::vector<int> payload_types;
144 for (const AudioCodec& codec : codecs) {
145 payload_types.push_back(codec.id);
146 }
147 std::sort(payload_types.begin(), payload_types.end());
148 auto it = std::unique(payload_types.begin(), payload_types.end());
149 return it == payload_types.end();
150}
151
minyue6b825df2016-10-31 04:08:32 -0700152rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
153 const AudioOptions& options) {
154 if (options.audio_network_adaptor && *options.audio_network_adaptor &&
155 options.audio_network_adaptor_config) {
156 // Turn on audio network adaptor only when |options_.audio_network_adaptor|
157 // equals true and |options_.audio_network_adaptor_config| has a value.
158 return options.audio_network_adaptor_config;
159 }
160 return rtc::Optional<std::string>();
161}
162
gyzhou95aa9642016-12-13 14:06:26 -0800163webrtc::AudioState::Config MakeAudioStateConfig(
164 VoEWrapper* voe_wrapper,
165 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
solenberg566ef242015-11-06 15:34:49 -0800166 webrtc::AudioState::Config config;
167 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800168 if (audio_mixer) {
169 config.audio_mixer = audio_mixer;
170 } else {
171 config.audio_mixer = webrtc::AudioMixerImpl::Create();
172 }
solenberg566ef242015-11-06 15:34:49 -0800173 return config;
174}
175
deadbeefe702b302017-02-04 12:09:01 -0800176// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
177// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700178rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800179 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700180 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800181 // If application-configured bitrate is set, take minimum of that and SDP
182 // bitrate.
183 const int bps = rtp_max_bitrate_bps
184 ? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
185 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700186 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700187 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700188 }
minyue7a973442016-10-20 03:27:12 -0700189
ossu20a4b3f2017-04-27 02:08:52 -0700190 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700191 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
192 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
193 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700194 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700195 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700196 << ", requires at least " << spec.info.min_bitrate_bps
197 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700198 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700199 }
ossu20a4b3f2017-04-27 02:08:52 -0700200
201 if (spec.info.HasFixedBitrate()) {
202 return rtc::Optional<int>(spec.info.default_bitrate_bps);
203 } else {
204 // If codec is multi-rate then just set the bitrate.
205 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
206 }
solenberg971cab02016-06-14 10:02:41 -0700207}
208
solenberg76377c52017-02-21 00:54:31 -0800209} // namespace
solenberg971cab02016-06-14 10:02:41 -0700210
ossu29b1a8d2016-06-13 07:34:51 -0700211WebRtcVoiceEngine::WebRtcVoiceEngine(
212 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700213 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800214 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
215 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer)
ossueb1fde42017-05-02 06:46:30 -0700216 : WebRtcVoiceEngine(adm,
217 encoder_factory,
218 decoder_factory,
219 audio_mixer,
220 new VoEWrapper()) {
gyzhou95aa9642016-12-13 14:06:26 -0800221 audio_state_ =
222 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer));
solenberg26c8c912015-11-27 04:00:25 -0800223}
224
ossu29b1a8d2016-06-13 07:34:51 -0700225WebRtcVoiceEngine::WebRtcVoiceEngine(
226 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700227 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700228 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800229 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
ossu29b1a8d2016-06-13 07:34:51 -0700230 VoEWrapper* voe_wrapper)
aleloife9ecb02017-05-26 05:46:34 -0700231 : adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700232 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700233 decoder_factory_(decoder_factory),
234 voe_wrapper_(voe_wrapper) {
solenberg26c8c912015-11-27 04:00:25 -0800235 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700236 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
237 RTC_DCHECK(voe_wrapper);
ossuc54071d2016-08-17 02:45:41 -0700238 RTC_DCHECK(decoder_factory);
solenberg26c8c912015-11-27 04:00:25 -0800239
240 signal_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800241
ossueb1fde42017-05-02 06:46:30 -0700242 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700243 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700244 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700245 for (const AudioCodec& codec : send_codecs_) {
246 LOG(LS_INFO) << ToString(codec);
247 }
248
249 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700250 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700251 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700252 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000253 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000254
solenberg88499ec2016-09-07 07:34:41 -0700255 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000256
solenbergff976312016-03-30 23:28:51 -0700257 // Temporarily turn logging level up for the Init() call.
258 webrtc::Trace::SetTraceCallback(this);
solenbergbd138382015-11-20 16:08:07 -0800259 webrtc::Trace::set_level_filter(kElevatedTraceFilter);
solenberg2515af22015-12-02 06:19:36 -0800260 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
ossu29b1a8d2016-06-13 07:34:51 -0700261 RTC_CHECK_EQ(0, voe_wrapper_->base()->Init(adm_.get(), nullptr,
262 decoder_factory_));
solenbergbd138382015-11-20 16:08:07 -0800263 webrtc::Trace::set_level_filter(kDefaultTraceFilter);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000264
solenbergff976312016-03-30 23:28:51 -0700265 // No ADM supplied? Get the default one from VoE.
266 if (!adm_) {
267 adm_ = voe_wrapper_->base()->audio_device_module();
268 }
269 RTC_DCHECK(adm_);
270
solenberg059fb442016-10-26 05:12:24 -0700271 apm_ = voe_wrapper_->base()->audio_processing();
272 RTC_DCHECK(apm_);
273
solenberg76377c52017-02-21 00:54:31 -0800274 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
275 RTC_DCHECK(transmit_mixer_);
276
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000277 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800278 // calling ApplyOptions or the default will be overwritten.
solenberg76377c52017-02-21 00:54:31 -0800279 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm_);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000280
solenberg0f7d2932016-01-15 01:40:39 -0800281 // Set default engine options.
282 {
283 AudioOptions options;
284 options.echo_cancellation = rtc::Optional<bool>(true);
285 options.auto_gain_control = rtc::Optional<bool>(true);
286 options.noise_suppression = rtc::Optional<bool>(true);
287 options.highpass_filter = rtc::Optional<bool>(true);
288 options.stereo_swapping = rtc::Optional<bool>(false);
289 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
290 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
291 options.typing_detection = rtc::Optional<bool>(true);
292 options.adjust_agc_delta = rtc::Optional<int>(0);
293 options.experimental_agc = rtc::Optional<bool>(false);
294 options.extended_filter_aec = rtc::Optional<bool>(false);
295 options.delay_agnostic_aec = rtc::Optional<bool>(false);
296 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700297 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700298 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800299 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700300 bool error = ApplyOptions(options);
301 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000302 }
303
solenberg9a5f032222017-03-15 06:14:12 -0700304 // Set default audio devices.
305#if !defined(WEBRTC_IOS)
306 webrtc::adm_helpers::SetRecordingDevice(adm_);
307 apm()->Initialize();
308 webrtc::adm_helpers::SetPlayoutDevice(adm_);
309#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000310}
311
solenbergff976312016-03-30 23:28:51 -0700312WebRtcVoiceEngine::~WebRtcVoiceEngine() {
solenberg566ef242015-11-06 15:34:49 -0800313 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700314 LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000315 StopAecDump();
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000316 voe_wrapper_->base()->Terminate();
solenbergff976312016-03-30 23:28:51 -0700317 webrtc::Trace::SetTraceCallback(nullptr);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000318}
319
solenberg566ef242015-11-06 15:34:49 -0800320rtc::scoped_refptr<webrtc::AudioState>
321 WebRtcVoiceEngine::GetAudioState() const {
322 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
323 return audio_state_;
324}
325
nisse51542be2016-02-12 02:27:06 -0800326VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
327 webrtc::Call* call,
328 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200329 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800330 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800331 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000332}
333
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000334bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700336 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800337 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800338
peah8a8ebd92017-05-22 15:48:47 -0700339 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000340 // kEcConference is AEC with high suppression.
341 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700342 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000343 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700344 << *options.aecm_generate_comfort_noise
345 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000346 }
347
kjellanderfcfc8042016-01-14 11:01:09 -0800348#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700349 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100350 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700351 options.extended_filter_aec = rtc::Optional<bool>(false);
352 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000353#elif defined(ANDROID)
354 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100355 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000356#endif
357
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100358 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
359 // where the feature is not supported.
360 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800361#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700362 if (options.delay_agnostic_aec) {
363 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100364 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100365 options.echo_cancellation = rtc::Optional<bool>(true);
366 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100367 ec_mode = webrtc::kEcConference;
368 }
369 }
370#endif
371
peah8a8ebd92017-05-22 15:48:47 -0700372// Set and adjust noise suppressor options.
373#if defined(WEBRTC_IOS)
374 // On iOS, VPIO provides built-in NS.
375 options.noise_suppression = rtc::Optional<bool>(false);
376 options.typing_detection = rtc::Optional<bool>(false);
377 options.experimental_ns = rtc::Optional<bool>(false);
378 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
379#elif defined(ANDROID)
380 options.typing_detection = rtc::Optional<bool>(false);
381 options.experimental_ns = rtc::Optional<bool>(false);
382#endif
383
384// Set and adjust gain control options.
385#if defined(WEBRTC_IOS)
386 // On iOS, VPIO provides built-in AGC.
387 options.auto_gain_control = rtc::Optional<bool>(false);
388 options.experimental_agc = rtc::Optional<bool>(false);
389 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
390#elif defined(ANDROID)
391 options.experimental_agc = rtc::Optional<bool>(false);
392#endif
393
394#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
395 // 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).
396 if (webrtc::field_trial::IsEnabled(
397 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
398 options.auto_gain_control = rtc::Optional<bool>(false);
399 LOG(LS_INFO) << "Disable AGC according to field trial.";
400 if (!(options.noise_suppression.value_or(false) or
401 options.echo_cancellation.value_or(false))) {
402 // If possible, turn off the high-pass filter.
403 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
404 options.highpass_filter = rtc::Optional<bool>(false);
405 }
406 }
407#endif
408
peah1bcfce52016-08-26 07:16:04 -0700409#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
410 // Hardcode the intelligibility enhancer to be off.
411 options.intelligibility_enhancer = rtc::Optional<bool>(false);
412#endif
413
kwiberg102c6a62015-10-30 02:47:38 -0700414 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000415 // Check if platform supports built-in EC. Currently only supported on
416 // Android and in combination with Java based audio layer.
417 // TODO(henrika): investigate possibility to support built-in EC also
418 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700419 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200420 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200421 // Built-in EC exists on this device and use_delay_agnostic_aec is not
422 // overriding it. Enable/Disable it according to the echo_cancellation
423 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200424 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700425 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700426 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200427 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100428 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000429 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100430 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000431 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
432 }
433 }
solenberg76377c52017-02-21 00:54:31 -0800434 webrtc::apm_helpers::SetEcStatus(
435 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000436#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800437 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000438#endif
439 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700440 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800441 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000442 }
443 }
444
kwiberg102c6a62015-10-30 02:47:38 -0700445 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700446 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
447 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700448 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700449 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200450 // Disable internal software AGC if built-in AGC is enabled,
451 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100452 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200453 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
454 }
455 }
solenberg22818a52017-03-16 01:20:23 -0700456 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000457 }
458
kwiberg102c6a62015-10-30 02:47:38 -0700459 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800460 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000461 // Override default_agc_config_. Generally, an unset option means "leave
462 // the VoE bits alone" in this function, so we want whatever is set to be
463 // stored as the new "default". If we didn't, then setting e.g.
464 // tx_agc_target_dbov would reset digital compression gain and limiter
465 // settings.
466 // Also, if we don't update default_agc_config_, then adjust_agc_delta
467 // would be an offset from the original values, and not whatever was set
468 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700469 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
470 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000471 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700472 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000473 default_agc_config_.digitalCompressionGaindB);
474 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700475 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800476
477 webrtc::AgcConfig config = default_agc_config_;
478 if (options.adjust_agc_delta) {
479 config.targetLeveldBOv -= *options.adjust_agc_delta;
480 LOG(LS_INFO) << "Adjusting AGC level from default -"
481 << default_agc_config_.targetLeveldBOv << "dB to -"
482 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000483 }
solenberg76377c52017-02-21 00:54:31 -0800484 webrtc::apm_helpers::SetAgcConfig(apm_, config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000485 }
486
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700487 if (options.intelligibility_enhancer) {
488 intelligibility_enhancer_ = options.intelligibility_enhancer;
489 }
490 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
491 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
492 options.noise_suppression = intelligibility_enhancer_;
493 }
494
kwiberg102c6a62015-10-30 02:47:38 -0700495 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700496 if (adm()->BuiltInNSIsAvailable()) {
497 bool builtin_ns =
498 *options.noise_suppression &&
499 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
500 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200501 // Disable internal software NS if built-in NS is enabled,
502 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100503 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200504 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
505 }
506 }
solenberg76377c52017-02-21 00:54:31 -0800507 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000508 }
509
kwiberg102c6a62015-10-30 02:47:38 -0700510 if (options.stereo_swapping) {
511 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800512 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000513 }
514
kwiberg102c6a62015-10-30 02:47:38 -0700515 if (options.audio_jitter_buffer_max_packets) {
516 LOG(LS_INFO) << "NetEq capacity is "
517 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700518 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
519 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200520 }
kwiberg102c6a62015-10-30 02:47:38 -0700521 if (options.audio_jitter_buffer_fast_accelerate) {
522 LOG(LS_INFO) << "NetEq fast mode? "
523 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700524 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
525 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200526 }
527
kwiberg102c6a62015-10-30 02:47:38 -0700528 if (options.typing_detection) {
529 LOG(LS_INFO) << "Typing detection is enabled? "
530 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800531 webrtc::apm_helpers::SetTypingDetectionStatus(
532 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000533 }
534
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000535 webrtc::Config config;
536
kwiberg102c6a62015-10-30 02:47:38 -0700537 if (options.delay_agnostic_aec)
538 delay_agnostic_aec_ = options.delay_agnostic_aec;
539 if (delay_agnostic_aec_) {
540 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700541 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700542 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100543 }
544
kwiberg102c6a62015-10-30 02:47:38 -0700545 if (options.extended_filter_aec) {
546 extended_filter_aec_ = options.extended_filter_aec;
547 }
548 if (extended_filter_aec_) {
549 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200550 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700551 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000552 }
553
kwiberg102c6a62015-10-30 02:47:38 -0700554 if (options.experimental_ns) {
555 experimental_ns_ = options.experimental_ns;
556 }
557 if (experimental_ns_) {
558 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000559 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700560 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000561 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000562
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700563 if (intelligibility_enhancer_) {
564 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
565 << *intelligibility_enhancer_;
566 config.Set<webrtc::Intelligibility>(
567 new webrtc::Intelligibility(*intelligibility_enhancer_));
568 }
569
peaha3333bf2016-06-30 00:02:34 -0700570 if (options.level_control) {
571 level_control_ = options.level_control;
572 }
573
574 LOG(LS_INFO) << "Level control: "
575 << (!!level_control_ ? *level_control_ : -1);
576 if (level_control_) {
peah64d6ff72016-11-21 06:28:14 -0800577 apm_config_.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700578 if (options.level_control_initial_peak_level_dbfs) {
peah64d6ff72016-11-21 06:28:14 -0800579 apm_config_.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700580 *options.level_control_initial_peak_level_dbfs;
581 }
peaha3333bf2016-06-30 00:02:34 -0700582 }
583
peah8271d042016-11-22 07:24:52 -0800584 if (options.highpass_filter) {
585 apm_config_.high_pass_filter.enabled = *options.highpass_filter;
586 }
587
ivoc4ca18692017-02-10 05:11:09 -0800588 if (options.residual_echo_detector) {
589 apm_config_.residual_echo_detector.enabled =
590 *options.residual_echo_detector;
591 }
592
solenberg059fb442016-10-26 05:12:24 -0700593 apm()->SetExtraOptions(config);
peah64d6ff72016-11-21 06:28:14 -0800594 apm()->ApplyConfig(apm_config_);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000595
kwiberg102c6a62015-10-30 02:47:38 -0700596 if (options.recording_sample_rate) {
597 LOG(LS_INFO) << "Recording sample rate is "
598 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700599 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700600 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000601 }
602 }
603
kwiberg102c6a62015-10-30 02:47:38 -0700604 if (options.playout_sample_rate) {
605 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700606 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700607 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000608 }
609 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000610 return true;
611}
612
solenberg796b8f92017-03-01 17:02:23 -0800613// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000614int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800615 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800616 int8_t level = transmit_mixer()->AudioLevel();
617 RTC_DCHECK_LE(0, level);
618 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619}
620
ossudedfd282016-06-14 07:12:39 -0700621const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
622 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700623 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700624}
625
626const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800627 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700628 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629}
630
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100631RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800632 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100633 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100634 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700635 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
636 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800637 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700638 capabilities.header_extensions.push_back(webrtc::RtpExtension(
639 webrtc::RtpExtension::kTransportSequenceNumberUri,
640 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800641 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100642 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643}
644
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800646 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 return voe_wrapper_->error();
648}
649
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
651 int length) {
solenberg566ef242015-11-06 15:34:49 -0800652 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000653 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000655 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000657 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000659 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000661 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662
solenberg72e29d22016-03-08 06:35:16 -0800663 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664 if (length < 72) {
665 std::string msg(trace, length);
666 LOG(LS_ERROR) << "Malformed webrtc log message: ";
667 LOG_V(sev) << msg;
668 } else {
669 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200670 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671 }
672}
673
solenberg63b34542015-09-29 06:06:31 -0700674void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800675 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
676 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 channels_.push_back(channel);
678}
679
solenberg63b34542015-09-29 06:06:31 -0700680void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800681 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700682 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800683 RTC_DCHECK(it != channels_.end());
684 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685}
686
ivocd66b44d2016-01-15 03:06:36 -0800687bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
688 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800689 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloife9ecb02017-05-26 05:46:34 -0700690 FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
691 if (!aec_dump_file_stream) {
692 LOG(LS_ERROR) << "Could not open AEC dump file stream.";
693 if (!rtc::ClosePlatformFile(file))
694 LOG(LS_WARNING) << "Could not close file.";
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000695 return false;
696 }
aleloife9ecb02017-05-26 05:46:34 -0700697 StopAecDump();
698 if (apm()->StartDebugRecording(aec_dump_file_stream, max_size_bytes) !=
699 webrtc::AudioProcessing::kNoError) {
700 LOG_RTCERR0(StartDebugRecording);
701 fclose(aec_dump_file_stream);
702 return false;
703 }
704 is_dumping_aec_ = true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000705 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000706}
707
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800709 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloife9ecb02017-05-26 05:46:34 -0700710 if (!is_dumping_aec_) {
711 // Start dumping AEC when we are not dumping.
712 if (apm()->StartDebugRecording(filename.c_str(), -1) !=
713 webrtc::AudioProcessing::kNoError) {
714 LOG_RTCERR1(StartDebugRecording, filename.c_str());
715 } else {
716 is_dumping_aec_ = true;
717 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 }
719}
720
721void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800722 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloife9ecb02017-05-26 05:46:34 -0700723 if (is_dumping_aec_) {
724 // Stop dumping AEC when we are dumping.
725 if (apm()->StopDebugRecording() != webrtc::AudioProcessing::kNoError) {
726 LOG_RTCERR0(StopDebugRecording);
727 }
728 is_dumping_aec_ = false;
729 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730}
731
solenberg0a617e22015-10-20 15:49:38 -0700732int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800733 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700734 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000735}
736
solenberg5b5129a2016-04-08 05:35:48 -0700737webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
738 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
739 RTC_DCHECK(adm_);
740 return adm_;
741}
742
solenberg059fb442016-10-26 05:12:24 -0700743webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
744 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
745 RTC_DCHECK(apm_);
746 return apm_;
747}
748
solenberg76377c52017-02-21 00:54:31 -0800749webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
750 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
751 RTC_DCHECK(transmit_mixer_);
752 return transmit_mixer_;
753}
754
ossu20a4b3f2017-04-27 02:08:52 -0700755AudioCodecs WebRtcVoiceEngine::CollectCodecs(
756 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700757 PayloadTypeMapper mapper;
758 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700759
solenberg2779bab2016-11-17 04:45:19 -0800760 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700761 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
762 { 16000, false },
763 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800764 // Only generate telephone-event payload types for these clockrates:
765 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
766 { 16000, false },
767 { 32000, false },
768 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700769
ossu9def8002017-02-09 05:14:32 -0800770 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
771 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700772 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800773 if (opt_codec) {
774 if (out) {
775 out->push_back(*opt_codec);
776 }
777 } else {
ossuc54071d2016-08-17 02:45:41 -0700778 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700779 }
780
ossu9def8002017-02-09 05:14:32 -0800781 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700782 };
783
ossud4e9f622016-08-18 02:01:17 -0700784 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800785 // We need to do some extra stuff before adding the main codecs to out.
786 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
787 if (opt_codec) {
788 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700789 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800790 codec.AddFeedbackParam(
791 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
792 }
793
ossua1a040a2017-04-06 10:03:21 -0700794 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800795 // Generate a CN entry if the decoder allows it and we support the
796 // clockrate.
797 auto cn = generate_cn.find(spec.format.clockrate_hz);
798 if (cn != generate_cn.end()) {
799 cn->second = true;
800 }
801 }
802
803 // Generate a telephone-event entry if we support the clockrate.
804 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
805 if (dtmf != generate_dtmf.end()) {
806 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700807 }
ossu9def8002017-02-09 05:14:32 -0800808
809 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700810 }
811 }
812
solenberg2779bab2016-11-17 04:45:19 -0800813 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700814 for (const auto& cn : generate_cn) {
815 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800816 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700817 }
818 }
819
solenberg2779bab2016-11-17 04:45:19 -0800820 // Add telephone-event codecs last.
821 for (const auto& dtmf : generate_dtmf) {
822 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800823 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800824 }
825 }
ossuc54071d2016-08-17 02:45:41 -0700826
827 return out;
828}
829
solenbergc96df772015-10-21 13:01:53 -0700830class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800831 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000832 public:
minyue7a973442016-10-20 03:27:12 -0700833 WebRtcAudioSendStream(
834 int ch,
835 webrtc::AudioTransport* voe_audio_transport,
836 uint32_t ssrc,
837 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700838 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
839 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700840 const std::vector<webrtc::RtpExtension>& extensions,
841 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700842 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700843 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700844 webrtc::Transport* send_transport,
845 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800846 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800847 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700848 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800849 send_side_bwe_with_overhead_(
850 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700851 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700852 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700853 RTC_DCHECK_GE(ch, 0);
854 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
855 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700856 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700857 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800858 config_.rtp.ssrc = ssrc;
859 config_.rtp.c_name = c_name;
860 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700861 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700862 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700863 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800864 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700865
866 if (send_codec_spec) {
867 UpdateSendCodecSpec(*send_codec_spec);
868 }
869
870 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700871 }
solenberg3a941542015-11-16 07:34:50 -0800872
solenbergc96df772015-10-21 13:01:53 -0700873 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800874 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800875 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700876 call_->DestroyAudioSendStream(stream_);
877 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000878
ossu20a4b3f2017-04-27 02:08:52 -0700879 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700880 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700881 UpdateSendCodecSpec(send_codec_spec);
882 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700883 }
884
ossu20a4b3f2017-04-27 02:08:52 -0700885 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800886 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800887 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700888 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800889 }
890
ossu20a4b3f2017-04-27 02:08:52 -0700891 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700892 const rtc::Optional<std::string>& audio_network_adaptor_config) {
893 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
894 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
895 return;
896 }
897 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700898 UpdateAllowedBitrateRange();
899 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700900 }
901
minyue7a973442016-10-20 03:27:12 -0700902 bool SetMaxSendBitrate(int bps) {
903 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700904 RTC_DCHECK(config_.send_codec_spec);
905 RTC_DCHECK(audio_codec_spec_);
906 auto send_rate = ComputeSendBitrate(
907 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
908
minyue7a973442016-10-20 03:27:12 -0700909 if (!send_rate) {
910 return false;
911 }
912
913 max_send_bitrate_bps_ = bps;
914
ossu20a4b3f2017-04-27 02:08:52 -0700915 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
916 config_.send_codec_spec->target_bitrate_bps = send_rate;
917 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700918 }
919 return true;
920 }
921
solenbergffbbcac2016-11-17 05:25:37 -0800922 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
923 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100924 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
925 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800926 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
927 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100928 }
929
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800930 void SetSend(bool send) {
931 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
932 send_ = send;
933 UpdateSendState();
934 }
935
solenberg94218532016-06-16 10:53:22 -0700936 void SetMuted(bool muted) {
937 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
938 RTC_DCHECK(stream_);
939 stream_->SetMuted(muted);
940 muted_ = muted;
941 }
942
943 bool muted() const {
944 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
945 return muted_;
946 }
947
solenberg3a941542015-11-16 07:34:50 -0800948 webrtc::AudioSendStream::Stats GetStats() const {
949 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
950 RTC_DCHECK(stream_);
951 return stream_->GetStats();
952 }
953
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800954 // Starts the sending by setting ourselves as a sink to the AudioSource to
955 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000956 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000957 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800958 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800959 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800960 RTC_DCHECK(source);
961 if (source_) {
962 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000963 return;
964 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800965 source->SetSink(this);
966 source_ = source;
967 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000968 }
969
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800970 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000971 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000972 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800973 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800974 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800975 if (source_) {
976 source_->SetSink(nullptr);
977 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700978 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800979 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000980 }
981
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800982 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000983 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000984 void OnData(const void* audio_data,
985 int bits_per_sample,
986 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800987 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700988 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -0700989 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -0700990 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -0700991 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
992 bits_per_sample, sample_rate,
993 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000994 }
995
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800996 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000997 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000998 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -0800999 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001000 // Set |source_| to nullptr to make sure no more callback will get into
1001 // the source.
1002 source_ = nullptr;
1003 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001004 }
1005
1006 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -07001007 int channel() const {
solenberg566ef242015-11-06 15:34:49 -08001008 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08001009 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -07001010 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001011
skvlade0d46372016-04-07 22:59:22 -07001012 const webrtc::RtpParameters& rtp_parameters() const {
1013 return rtp_parameters_;
1014 }
1015
deadbeeffb2aced2017-01-06 23:05:37 -08001016 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1017 if (rtp_parameters.encodings.size() != 1) {
1018 LOG(LS_ERROR)
1019 << "Attempted to set RtpParameters without exactly one encoding";
1020 return false;
1021 }
1022 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1023 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1024 return false;
1025 }
1026 return true;
1027 }
1028
minyue7a973442016-10-20 03:27:12 -07001029 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001030 if (!ValidateRtpParameters(parameters)) {
1031 return false;
1032 }
ossu20a4b3f2017-04-27 02:08:52 -07001033
1034 rtc::Optional<int> send_rate;
1035 if (audio_codec_spec_) {
1036 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1037 parameters.encodings[0].max_bitrate_bps,
1038 *audio_codec_spec_);
1039 if (!send_rate) {
1040 return false;
1041 }
minyue7a973442016-10-20 03:27:12 -07001042 }
1043
minyuececec102017-03-27 13:04:25 -07001044 const rtc::Optional<int> old_rtp_max_bitrate =
1045 rtp_parameters_.encodings[0].max_bitrate_bps;
1046
skvlade0d46372016-04-07 22:59:22 -07001047 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001048
minyuececec102017-03-27 13:04:25 -07001049 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001050 // Reconfigure AudioSendStream with new bit rate.
1051 if (send_rate) {
1052 config_.send_codec_spec->target_bitrate_bps = send_rate;
1053 }
1054 UpdateAllowedBitrateRange();
1055 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001056 } else {
1057 // parameters.encodings[0].active could have changed.
1058 UpdateSendState();
1059 }
1060 return true;
skvlade0d46372016-04-07 22:59:22 -07001061 }
1062
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001063 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001064 void UpdateSendState() {
1065 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1066 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001067 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1068 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001069 stream_->Start();
1070 } else { // !send || source_ = nullptr
1071 stream_->Stop();
1072 }
1073 }
1074
ossu20a4b3f2017-04-27 02:08:52 -07001075 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001076 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001077 const bool is_opus =
1078 config_.send_codec_spec &&
1079 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1080 kOpusCodecName);
1081 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001082 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001083
1084 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001085 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001086 // meanwhile change the cap to the output of BWE.
1087 config_.max_bitrate_bps =
1088 rtp_parameters_.encodings[0].max_bitrate_bps
1089 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1090 : kOpusBitrateFbBps;
1091
michaelt53fe19d2016-10-18 09:39:22 -07001092 // TODO(mflodman): Keep testing this and set proper values.
1093 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001094 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001095 const int max_packet_size_ms =
1096 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001097
ossu20a4b3f2017-04-27 02:08:52 -07001098 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1099 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001100
ossu20a4b3f2017-04-27 02:08:52 -07001101 int min_overhead_bps =
1102 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001103
ossu20a4b3f2017-04-27 02:08:52 -07001104 // We assume that |config_.max_bitrate_bps| before the next line is
1105 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1106 // it to ensure that, when overhead is deducted, the payload rate
1107 // never goes beyond the limit.
1108 // Note: this also means that if a higher overhead is forced, we
1109 // cannot reach the limit.
1110 // TODO(minyue): Reconsider this when the signaling to BWE is done
1111 // through a dedicated API.
1112 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001113
ossu20a4b3f2017-04-27 02:08:52 -07001114 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1115 // reachable.
1116 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001117 }
michaelt53fe19d2016-10-18 09:39:22 -07001118 }
ossu20a4b3f2017-04-27 02:08:52 -07001119 }
1120
1121 void UpdateSendCodecSpec(
1122 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1123 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1124 config_.rtp.nack.rtp_history_ms =
1125 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1126 config_.send_codec_spec =
1127 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1128 send_codec_spec);
1129 auto info =
1130 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1131 RTC_DCHECK(info);
1132 // If a specific target bitrate has been set for the stream, use that as
1133 // the new default bitrate when computing send bitrate.
1134 if (send_codec_spec.target_bitrate_bps) {
1135 info->default_bitrate_bps = std::max(
1136 info->min_bitrate_bps,
1137 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1138 }
1139
1140 audio_codec_spec_.emplace(
1141 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1142
1143 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1144 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1145 *audio_codec_spec_);
1146
1147 UpdateAllowedBitrateRange();
1148 }
1149
1150 void ReconfigureAudioSendStream() {
1151 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1152 RTC_DCHECK(stream_);
1153 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001154 }
1155
solenberg566ef242015-11-06 15:34:49 -08001156 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001157 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001158 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1159 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001160 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001161 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001162 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1163 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001164 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001165
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001166 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001167 // PeerConnection will make sure invalidating the pointer before the object
1168 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001169 AudioSource* source_ = nullptr;
1170 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001171 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001172 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001173 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001174 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001175
solenbergc96df772015-10-21 13:01:53 -07001176 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1177};
1178
1179class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1180 public:
ossu29b1a8d2016-06-13 07:34:51 -07001181 WebRtcAudioReceiveStream(
1182 int ch,
1183 uint32_t remote_ssrc,
1184 uint32_t local_ssrc,
1185 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001186 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001187 const std::string& sync_group,
1188 const std::vector<webrtc::RtpExtension>& extensions,
1189 webrtc::Call* call,
1190 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001191 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1192 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001193 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001194 RTC_DCHECK_GE(ch, 0);
1195 RTC_DCHECK(call);
1196 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001197 config_.rtp.local_ssrc = local_ssrc;
1198 config_.rtp.transport_cc = use_transport_cc;
1199 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1200 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001201 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001202 config_.voe_channel_id = ch;
1203 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001204 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001205 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001206 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001207 }
solenbergc96df772015-10-21 13:01:53 -07001208
solenberg7add0582015-11-20 09:59:34 -08001209 ~WebRtcAudioReceiveStream() {
1210 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1211 call_->DestroyAudioReceiveStream(stream_);
1212 }
1213
solenberg4a0f7b52016-06-16 13:07:33 -07001214 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001215 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001216 config_.rtp.local_ssrc = local_ssrc;
1217 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001218 }
solenberg8189b022016-06-14 12:13:00 -07001219
1220 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001221 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001222 config_.rtp.transport_cc = use_transport_cc;
1223 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1224 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001225 }
1226
solenberg4a0f7b52016-06-16 13:07:33 -07001227 void RecreateAudioReceiveStream(
1228 const std::vector<webrtc::RtpExtension>& extensions) {
1229 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001230 config_.rtp.extensions = extensions;
1231 RecreateAudioReceiveStream();
1232 }
1233
deadbeefcb383672017-04-26 16:28:42 -07001234 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001235 void RecreateAudioReceiveStream(
1236 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001238 config_.decoder_map = decoder_map;
1239 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001240 }
1241
solenberg4904fb62017-02-17 12:01:14 -08001242 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1243 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1244 if (config_.sync_group != sync_group) {
1245 config_.sync_group = sync_group;
1246 RecreateAudioReceiveStream();
1247 }
1248 }
1249
solenberg7add0582015-11-20 09:59:34 -08001250 webrtc::AudioReceiveStream::Stats GetStats() const {
1251 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1252 RTC_DCHECK(stream_);
1253 return stream_->GetStats();
1254 }
1255
solenberg796b8f92017-03-01 17:02:23 -08001256 int GetOutputLevel() const {
1257 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1258 RTC_DCHECK(stream_);
1259 return stream_->GetOutputLevel();
1260 }
1261
solenberg7add0582015-11-20 09:59:34 -08001262 int channel() const {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 return config_.voe_channel_id;
1265 }
solenbergc96df772015-10-21 13:01:53 -07001266
kwiberg686a8ef2016-02-26 03:00:35 -08001267 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001268 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001269 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001270 }
1271
solenberg217fb662016-06-17 08:30:54 -07001272 void SetOutputVolume(double volume) {
1273 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1274 stream_->SetGain(volume);
1275 }
1276
aleloi84ef6152016-08-04 05:28:21 -07001277 void SetPlayout(bool playout) {
1278 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1279 RTC_DCHECK(stream_);
1280 if (playout) {
1281 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1282 stream_->Start();
1283 } else {
1284 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1285 stream_->Stop();
1286 }
aleloi18e0b672016-10-04 02:45:47 -07001287 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001288 }
1289
hbos8d609f62017-04-10 07:39:05 -07001290 std::vector<webrtc::RtpSource> GetSources() {
1291 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1292 RTC_DCHECK(stream_);
1293 return stream_->GetSources();
1294 }
1295
solenbergc96df772015-10-21 13:01:53 -07001296 private:
kwibergd32bf752017-01-19 07:03:59 -08001297 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001298 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1299 if (stream_) {
1300 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001301 }
solenberg7add0582015-11-20 09:59:34 -08001302 stream_ = call_->CreateAudioReceiveStream(config_);
1303 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001304 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001305 }
1306
1307 rtc::ThreadChecker worker_thread_checker_;
1308 webrtc::Call* call_ = nullptr;
1309 webrtc::AudioReceiveStream::Config config_;
1310 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1311 // configuration changes.
1312 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001313 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001314
1315 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001316};
1317
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001318WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001319 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001320 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001321 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001322 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001323 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001324 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001325 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001326 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001327}
1328
1329WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001330 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001331 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001332 // TODO(solenberg): Should be able to delete the streams directly, without
1333 // going through RemoveNnStream(), once stream objects handle
1334 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001335 while (!send_streams_.empty()) {
1336 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001337 }
solenberg7add0582015-11-20 09:59:34 -08001338 while (!recv_streams_.empty()) {
1339 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 }
solenberg0a617e22015-10-20 15:49:38 -07001341 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342}
1343
nisse51542be2016-02-12 02:27:06 -08001344rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1345 return kAudioDscpValue;
1346}
1347
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001348bool WebRtcVoiceMediaChannel::SetSendParameters(
1349 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001350 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001351 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001352 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1353 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001354 // TODO(pthatcher): Refactor this to be more clean now that we have
1355 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001356
1357 if (!SetSendCodecs(params.codecs)) {
1358 return false;
1359 }
1360
solenberg7e4e01a2015-12-02 08:05:01 -08001361 if (!ValidateRtpExtensions(params.extensions)) {
1362 return false;
1363 }
1364 std::vector<webrtc::RtpExtension> filtered_extensions =
1365 FilterRtpExtensions(params.extensions,
1366 webrtc::RtpExtension::IsSupportedForAudio, true);
1367 if (send_rtp_extensions_ != filtered_extensions) {
1368 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001369 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001370 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001371 }
1372 }
1373
deadbeef80346142016-04-27 14:17:10 -07001374 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001375 return false;
1376 }
1377 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001378}
1379
1380bool WebRtcVoiceMediaChannel::SetRecvParameters(
1381 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001382 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001383 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001384 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1385 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001386 // TODO(pthatcher): Refactor this to be more clean now that we have
1387 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001388
1389 if (!SetRecvCodecs(params.codecs)) {
1390 return false;
1391 }
1392
solenberg7e4e01a2015-12-02 08:05:01 -08001393 if (!ValidateRtpExtensions(params.extensions)) {
1394 return false;
1395 }
1396 std::vector<webrtc::RtpExtension> filtered_extensions =
1397 FilterRtpExtensions(params.extensions,
1398 webrtc::RtpExtension::IsSupportedForAudio, false);
1399 if (recv_rtp_extensions_ != filtered_extensions) {
1400 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001401 for (auto& it : recv_streams_) {
1402 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1403 }
1404 }
solenberg7add0582015-11-20 09:59:34 -08001405 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001406}
1407
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001408webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001409 uint32_t ssrc) const {
1410 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1411 auto it = send_streams_.find(ssrc);
1412 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001413 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1414 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001415 return webrtc::RtpParameters();
1416 }
1417
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001418 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1419 // Need to add the common list of codecs to the send stream-specific
1420 // RTP parameters.
1421 for (const AudioCodec& codec : send_codecs_) {
1422 rtp_params.codecs.push_back(codec.ToCodecParameters());
1423 }
1424 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001425}
1426
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001427bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001428 uint32_t ssrc,
1429 const webrtc::RtpParameters& parameters) {
1430 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001431 auto it = send_streams_.find(ssrc);
1432 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001433 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1434 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001435 return false;
1436 }
1437
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001438 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1439 // different order (which should change the send codec).
1440 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1441 if (current_parameters.codecs != parameters.codecs) {
1442 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1443 << "is not currently supported.";
1444 return false;
1445 }
1446
minyue7a973442016-10-20 03:27:12 -07001447 // TODO(minyue): The following legacy actions go into
1448 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1449 // though there are two difference:
1450 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1451 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1452 // |SetSendCodecs|. The outcome should be the same.
1453 // 2. AudioSendStream can be recreated.
1454
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001455 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1456 webrtc::RtpParameters reduced_params = parameters;
1457 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001458 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001459}
1460
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001461webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1462 uint32_t ssrc) const {
1463 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001464 webrtc::RtpParameters rtp_params;
1465 // SSRC of 0 represents the default receive stream.
1466 if (ssrc == 0) {
1467 if (!default_sink_) {
1468 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1469 "unsignaled audio receive stream, but not yet "
1470 "configured to receive such a stream.";
1471 return rtp_params;
1472 }
1473 rtp_params.encodings.emplace_back();
1474 } else {
1475 auto it = recv_streams_.find(ssrc);
1476 if (it == recv_streams_.end()) {
1477 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1478 << "with ssrc " << ssrc << " which doesn't exist.";
1479 return webrtc::RtpParameters();
1480 }
1481 rtp_params.encodings.emplace_back();
1482 // TODO(deadbeef): Return stream-specific parameters.
1483 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001484 }
1485
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001486 for (const AudioCodec& codec : recv_codecs_) {
1487 rtp_params.codecs.push_back(codec.ToCodecParameters());
1488 }
1489 return rtp_params;
1490}
1491
1492bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1493 uint32_t ssrc,
1494 const webrtc::RtpParameters& parameters) {
1495 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001496 // SSRC of 0 represents the default receive stream.
1497 if (ssrc == 0) {
1498 if (!default_sink_) {
1499 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1500 "unsignaled audio receive stream, but not yet "
1501 "configured to receive such a stream.";
1502 return false;
1503 }
1504 } else {
1505 auto it = recv_streams_.find(ssrc);
1506 if (it == recv_streams_.end()) {
1507 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1508 << "with ssrc " << ssrc << " which doesn't exist.";
1509 return false;
1510 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001511 }
1512
1513 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1514 if (current_parameters != parameters) {
1515 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1516 << "unsupported.";
1517 return false;
1518 }
1519 return true;
1520}
1521
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001523 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 LOG(LS_INFO) << "Setting voice channel options: "
1525 << options.ToString();
1526
1527 // We retain all of the existing options, and apply the given ones
1528 // on top. This means there is no way to "clear" options such that
1529 // they go back to the engine default.
1530 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001531 if (!engine()->ApplyOptions(options_)) {
1532 LOG(LS_WARNING) <<
1533 "Failed to apply engine options during channel SetOptions.";
1534 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001535 }
minyue6b825df2016-10-31 04:08:32 -07001536
ossu20a4b3f2017-04-27 02:08:52 -07001537 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001538 GetAudioNetworkAdaptorConfig(options_);
1539 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001540 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001541 }
1542
solenberg76377c52017-02-21 00:54:31 -08001543 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544 << options_.ToString();
1545 return true;
1546}
1547
1548bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1549 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001550 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001551
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001553 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001554
1555 if (!VerifyUniquePayloadTypes(codecs)) {
1556 LOG(LS_ERROR) << "Codec payload types overlap.";
1557 return false;
1558 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559
kwibergd32bf752017-01-19 07:03:59 -08001560 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1561 // unless the factory claims to support all decoders.
1562 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1563 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001564 // Log a warning if a codec's payload type is changing. This used to be
1565 // treated as an error. It's abnormal, but not really illegal.
1566 AudioCodec old_codec;
1567 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1568 old_codec.id != codec.id) {
1569 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1570 << codec.id << ", was already mapped to " << old_codec.id
1571 << ")";
1572 }
kwibergd32bf752017-01-19 07:03:59 -08001573 auto format = AudioCodecToSdpAudioFormat(codec);
1574 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1575 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1576 LOG(LS_ERROR) << "Unsupported codec: " << format;
1577 return false;
1578 }
deadbeefcb383672017-04-26 16:28:42 -07001579 // We allow adding new codecs but don't allow changing the payload type of
1580 // codecs that are already configured since we might already be receiving
1581 // packets with that payload type. See RFC3264, Section 8.3.2.
1582 // TODO(deadbeef): Also need to check for clashes with previously mapped
1583 // payload types, and not just currently mapped ones. For example, this
1584 // should be illegal:
1585 // 1. {100: opus/48000/2, 101: ISAC/16000}
1586 // 2. {100: opus/48000/2}
1587 // 3. {100: opus/48000/2, 101: ISAC/32000}
1588 // Though this check really should happen at a higher level, since this
1589 // conflict could happen between audio and video codecs.
1590 auto existing = decoder_map_.find(codec.id);
1591 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1592 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1593 << codec.name << ", but it is already used for "
1594 << existing->second.name;
1595 return false;
1596 }
kwibergd32bf752017-01-19 07:03:59 -08001597 decoder_map.insert({codec.id, std::move(format)});
1598 }
1599
deadbeefcb383672017-04-26 16:28:42 -07001600 if (decoder_map == decoder_map_) {
1601 // There's nothing new to configure.
1602 return true;
1603 }
1604
kwiberg37b8b112016-11-03 02:46:53 -07001605 if (playout_) {
1606 // Receive codecs can not be changed while playing. So we temporarily
1607 // pause playout.
1608 ChangePlayout(false);
1609 }
1610
kwiberg1c07c702017-03-27 07:15:49 -07001611 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001612 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001613 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001614 }
kwibergd32bf752017-01-19 07:03:59 -08001615 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616
kwiberg37b8b112016-11-03 02:46:53 -07001617 if (desired_playout_ && !playout_) {
1618 ChangePlayout(desired_playout_);
1619 }
kwibergd32bf752017-01-19 07:03:59 -08001620 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621}
1622
solenberg72e29d22016-03-08 06:35:16 -08001623// Utility function called from SetSendParameters() to extract current send
1624// codec settings from the given list of codecs (originally from SDP). Both send
1625// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001626bool WebRtcVoiceMediaChannel::SetSendCodecs(
1627 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001628 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001629 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001630 dtmf_payload_freq_ = -1;
1631
1632 // Validate supplied codecs list.
1633 for (const AudioCodec& codec : codecs) {
1634 // TODO(solenberg): Validate more aspects of input - that payload types
1635 // don't overlap, remove redundant/unsupported codecs etc -
1636 // the same way it is done for RtpHeaderExtensions.
1637 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1638 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1639 return false;
1640 }
1641 }
1642
1643 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1644 // case we don't have a DTMF codec with a rate matching the send codec's, or
1645 // if this function returns early.
1646 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001647 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001648 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001649 dtmf_codecs.push_back(codec);
1650 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1651 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1652 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001653 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001654 }
1655 }
1656
ossu20a4b3f2017-04-27 02:08:52 -07001657 // Scan through the list to figure out the codec to use for sending.
1658 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001659 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001660 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1661 for (const AudioCodec& voice_codec : codecs) {
1662 if (!(IsCodec(voice_codec, kCnCodecName) ||
1663 IsCodec(voice_codec, kDtmfCodecName) ||
1664 IsCodec(voice_codec, kRedCodecName))) {
1665 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1666 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001667
ossu20a4b3f2017-04-27 02:08:52 -07001668 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1669 if (!voice_codec_info) {
1670 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001671 continue;
1672 }
1673
ossu20a4b3f2017-04-27 02:08:52 -07001674 send_codec_spec =
1675 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1676 {voice_codec.id, format});
1677 if (voice_codec.bitrate > 0) {
1678 send_codec_spec->target_bitrate_bps =
1679 rtc::Optional<int>(voice_codec.bitrate);
1680 }
1681 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1682 send_codec_spec->nack_enabled = HasNack(voice_codec);
1683 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1684 break;
1685 }
1686 }
1687
1688 if (!send_codec_spec) {
1689 return false;
1690 }
1691
1692 RTC_DCHECK(voice_codec_info);
1693 if (voice_codec_info->allow_comfort_noise) {
1694 // Loop through the codecs list again to find the CN codec.
1695 // TODO(solenberg): Break out into a separate function?
1696 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001697 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001698 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001699 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001700 case 8000:
1701 case 16000:
1702 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001703 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001704 break;
1705 default:
ossu0c4b8492017-03-02 11:03:25 -08001706 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001707 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001708 break;
solenberg72e29d22016-03-08 06:35:16 -08001709 }
solenberg72e29d22016-03-08 06:35:16 -08001710 break;
1711 }
1712 }
solenbergffbbcac2016-11-17 05:25:37 -08001713
1714 // Find the telephone-event PT exactly matching the preferred send codec.
1715 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001716 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001717 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1718 dtmf_payload_freq_ = dtmf_codec.clockrate;
1719 break;
1720 }
1721 }
solenberg72e29d22016-03-08 06:35:16 -08001722 }
1723
solenberg971cab02016-06-14 10:02:41 -07001724 if (send_codec_spec_ != send_codec_spec) {
1725 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001726 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001727 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001728 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001729 }
stefan13f1a0a2016-11-30 07:22:58 -08001730 } else {
1731 // If the codec isn't changing, set the start bitrate to -1 which means
1732 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001733 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001734 }
stefan1ccf73f2017-03-27 03:51:18 -07001735 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001736
solenberg8189b022016-06-14 12:13:00 -07001737 // Check if the transport cc feedback or NACK status has changed on the
1738 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001739 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1740 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001741 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1742 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001743 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1744 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001745 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001746 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1747 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001748 }
1749 }
1750
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001751 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001752 return true;
1753}
1754
aleloi84ef6152016-08-04 05:28:21 -07001755void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001756 desired_playout_ = playout;
1757 return ChangePlayout(desired_playout_);
1758}
1759
1760void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1761 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001762 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001764 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001765 }
1766
aleloi84ef6152016-08-04 05:28:21 -07001767 for (const auto& kv : recv_streams_) {
1768 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769 }
solenberg1ac56142015-10-13 03:58:19 -07001770 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771}
1772
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001773void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001774 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001775 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001776 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 }
1778
solenbergd53a3f92016-04-14 13:56:37 -07001779 // Apply channel specific options, and initialize the ADM for recording (this
1780 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001781 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001782 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001783
1784 // InitRecording() may return an error if the ADM is already recording.
1785 if (!engine()->adm()->RecordingIsInitialized() &&
1786 !engine()->adm()->Recording()) {
1787 if (engine()->adm()->InitRecording() != 0) {
1788 LOG(LS_WARNING) << "Failed to initialize recording";
1789 }
1790 }
solenberg63b34542015-09-29 06:06:31 -07001791 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001793 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001794 for (auto& kv : send_streams_) {
1795 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001797
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001799}
1800
Peter Boström0c4e06b2015-10-07 12:23:21 +02001801bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1802 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001803 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001804 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001805 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001806 // TODO(solenberg): The state change should be fully rolled back if any one of
1807 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001808 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001809 return false;
1810 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001811 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001812 return false;
1813 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001814 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001815 return SetOptions(*options);
1816 }
1817 return true;
1818}
1819
solenberg0a617e22015-10-20 15:49:38 -07001820int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1821 int id = engine()->CreateVoEChannel();
1822 if (id == -1) {
1823 LOG_RTCERR0(CreateVoEChannel);
1824 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001825 }
mflodman3d7db262016-04-29 00:57:13 -07001826
solenberg0a617e22015-10-20 15:49:38 -07001827 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001828}
1829
solenberg7add0582015-11-20 09:59:34 -08001830bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001831 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1832 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833 return false;
1834 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001835 return true;
1836}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001837
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001838bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001839 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001840 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001841 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1842
1843 uint32_t ssrc = sp.first_ssrc();
1844 RTC_DCHECK(0 != ssrc);
1845
1846 if (GetSendChannelId(ssrc) != -1) {
1847 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001848 return false;
1849 }
1850
solenberg0a617e22015-10-20 15:49:38 -07001851 // Create a new channel for sending audio data.
1852 int channel = CreateVoEChannel();
1853 if (channel == -1) {
1854 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001855 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001856
solenbergc96df772015-10-21 13:01:53 -07001857 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001858 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001859 webrtc::AudioTransport* audio_transport =
1860 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001861
minyue6b825df2016-10-31 04:08:32 -07001862 rtc::Optional<std::string> audio_network_adaptor_config =
1863 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001864 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001865 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001866 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001867 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001868 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001869
solenberg4a0f7b52016-06-16 13:07:33 -07001870 // At this point the stream's local SSRC has been updated. If it is the first
1871 // send stream, make sure that all the receive streams are updated with the
1872 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001873 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001874 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001875 for (const auto& kv : recv_streams_) {
1876 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1877 // streams instead, so we can avoid recreating the streams here.
1878 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001879 }
1880 }
1881
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001882 send_streams_[ssrc]->SetSend(send_);
1883 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001884}
1885
Peter Boström0c4e06b2015-10-07 12:23:21 +02001886bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001887 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001888 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001889 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1890
solenbergc96df772015-10-21 13:01:53 -07001891 auto it = send_streams_.find(ssrc);
1892 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001893 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1894 << " which doesn't exist.";
1895 return false;
1896 }
1897
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001898 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001899
solenberg7602aab2016-11-14 11:30:07 -08001900 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1901 // the first active send stream and use that instead, reassociating receive
1902 // streams.
1903
solenberg7add0582015-11-20 09:59:34 -08001904 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001905 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001906 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1907 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001908 delete it->second;
1909 send_streams_.erase(it);
1910 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001911 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001912 }
solenbergc96df772015-10-21 13:01:53 -07001913 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001914 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001915 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001916 return true;
1917}
1918
1919bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001920 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001921 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001922 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1923
solenberg0b675462015-10-09 01:37:09 -07001924 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001925 return false;
1926 }
1927
solenberg7add0582015-11-20 09:59:34 -08001928 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001929 if (ssrc == 0) {
1930 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1931 return false;
1932 }
1933
solenberg2100c0b2017-03-01 11:29:29 -08001934 // If this stream was previously received unsignaled, we promote it, possibly
1935 // recreating the AudioReceiveStream, if sync_label has changed.
1936 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001937 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001938 return true;
solenberg1ac56142015-10-13 03:58:19 -07001939 }
solenberg0b675462015-10-09 01:37:09 -07001940
solenberg7add0582015-11-20 09:59:34 -08001941 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001942 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001943 return false;
1944 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001945
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001947 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001949 return false;
1950 }
Minyue2013aec2015-05-13 14:14:42 +02001951
stefanba4c0e42016-02-04 04:12:24 -08001952 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001953 ssrc,
1954 new WebRtcAudioReceiveStream(
1955 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1956 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1957 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001958 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001959
solenberg1ac56142015-10-13 03:58:19 -07001960 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961}
1962
Peter Boström0c4e06b2015-10-07 12:23:21 +02001963bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001964 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001965 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001966 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1967
solenberg7add0582015-11-20 09:59:34 -08001968 const auto it = recv_streams_.find(ssrc);
1969 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001970 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1971 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001972 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001973 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974
solenberg2100c0b2017-03-01 11:29:29 -08001975 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001976
solenberg7add0582015-11-20 09:59:34 -08001977 const int channel = it->second->channel();
1978
1979 // Clean up and delete the receive stream+channel.
1980 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001981 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001982 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001983 delete it->second;
1984 recv_streams_.erase(it);
1985 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986}
1987
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001988bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
1989 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07001990 auto it = send_streams_.find(ssrc);
1991 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001992 if (source) {
1993 // Return an error if trying to set a valid source with an invalid ssrc.
1994 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001995 return false;
1996 }
1997
1998 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001999 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002000 }
2001
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002002 if (source) {
2003 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07002004 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002005 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07002006 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002007
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002008 return true;
2009}
2010
solenberg796b8f92017-03-01 17:02:23 -08002011// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012bool WebRtcVoiceMediaChannel::GetActiveStreams(
2013 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08002014 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002015 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002016 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002017 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002019 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020 }
2021 }
2022 return true;
2023}
2024
solenberg796b8f92017-03-01 17:02:23 -08002025// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002027 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002028 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002029 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002030 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 }
2032 return highest;
2033}
2034
solenberg4bac9c52015-10-09 02:32:53 -07002035bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002036 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002037 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002038 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002039 if (ssrc == 0) {
2040 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002041 ssrcs = unsignaled_recv_ssrcs_;
2042 }
2043 for (uint32_t ssrc : ssrcs) {
2044 const auto it = recv_streams_.find(ssrc);
2045 if (it == recv_streams_.end()) {
2046 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2047 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002048 }
solenberg2100c0b2017-03-01 11:29:29 -08002049 it->second->SetOutputVolume(volume);
2050 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2051 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002052 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053 return true;
2054}
2055
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002057 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058}
2059
solenberg1d63dd02015-12-02 12:35:09 -08002060bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2061 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002062 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002063 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2064 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 return false;
2066 }
2067
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002068 // Figure out which WebRtcAudioSendStream to send the event on.
2069 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2070 if (it == send_streams_.end()) {
2071 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002072 return false;
2073 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002074 if (event < kMinTelephoneEventCode ||
2075 event > kMaxTelephoneEventCode) {
2076 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002077 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002078 }
solenbergffbbcac2016-11-17 05:25:37 -08002079 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2080 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2081 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082}
2083
wu@webrtc.orga9890802013-12-13 00:21:03 +00002084void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002085 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002086 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002087
mflodman3d7db262016-04-29 00:57:13 -07002088 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2089 packet_time.not_before);
2090 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2091 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2092 packet->cdata(), packet->size(),
2093 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002094 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2095 return;
2096 }
2097
solenberg2100c0b2017-03-01 11:29:29 -08002098 // Create an unsignaled receive stream for this previously not received ssrc.
2099 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002100 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002101 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002102 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002103 return;
2104 }
solenberg2100c0b2017-03-01 11:29:29 -08002105 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2106 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002107
solenberg2100c0b2017-03-01 11:29:29 -08002108 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002109 StreamParams sp;
2110 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002111 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002112 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002113 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002114 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 }
solenberg2100c0b2017-03-01 11:29:29 -08002116 unsignaled_recv_ssrcs_.push_back(ssrc);
2117 RTC_HISTOGRAM_COUNTS_LINEAR(
2118 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2119 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002120
solenberg2100c0b2017-03-01 11:29:29 -08002121 // Remove oldest unsignaled stream, if we have too many.
2122 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2123 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2124 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2125 << remove_ssrc;
2126 RemoveRecvStream(remove_ssrc);
2127 }
2128 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2129
2130 SetOutputVolume(ssrc, default_recv_volume_);
2131
2132 // The default sink can only be attached to one stream at a time, so we hook
2133 // it up to the *latest* unsignaled stream we've seen, in order to support the
2134 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002135 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002136 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2137 auto it = recv_streams_.find(drop_ssrc);
2138 it->second->SetRawAudioSink(nullptr);
2139 }
mflodman3d7db262016-04-29 00:57:13 -07002140 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2141 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002142 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002143 }
solenberg2100c0b2017-03-01 11:29:29 -08002144
mflodman3d7db262016-04-29 00:57:13 -07002145 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2146 packet->cdata(),
2147 packet->size(),
2148 webrtc_packet_time);
2149 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002150}
2151
wu@webrtc.orga9890802013-12-13 00:21:03 +00002152void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002153 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002154 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002155
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002156 // Forward packet to Call as well.
2157 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2158 packet_time.not_before);
2159 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002160 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161}
2162
Honghai Zhangcc411c02016-03-29 17:27:21 -07002163void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2164 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002165 const rtc::NetworkRoute& network_route) {
2166 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002167}
2168
Peter Boström0c4e06b2015-10-07 12:23:21 +02002169bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002170 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002171 const auto it = send_streams_.find(ssrc);
2172 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2174 return false;
2175 }
solenberg94218532016-06-16 10:53:22 -07002176 it->second->SetMuted(muted);
2177
2178 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002179 // We set the AGC to mute state only when all the channels are muted.
2180 // This implementation is not ideal, instead we should signal the AGC when
2181 // the mic channel is muted/unmuted. We can't do it today because there
2182 // is no good way to know which stream is mapping to the mic channel.
2183 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002184 for (const auto& kv : send_streams_) {
2185 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002186 }
solenberg059fb442016-10-26 05:12:24 -07002187 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002188
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002189 return true;
2190}
2191
deadbeef80346142016-04-27 14:17:10 -07002192bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2193 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2194 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002195 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002196 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002197 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2198 success = false;
skvlade0d46372016-04-07 22:59:22 -07002199 }
2200 }
minyue7a973442016-10-20 03:27:12 -07002201 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002202}
2203
skvlad7a43d252016-03-22 15:32:27 -07002204void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2205 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2206 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2207 call_->SignalChannelNetworkState(
2208 webrtc::MediaType::AUDIO,
2209 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2210}
2211
michaelt79e05882016-11-08 02:50:09 -08002212void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2213 int transport_overhead_per_packet) {
2214 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2215 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2216 transport_overhead_per_packet);
2217}
2218
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002219bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002220 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002221 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002222 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002223
solenberg85a04962015-10-27 03:35:21 -07002224 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002225 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002226 for (const auto& stream : send_streams_) {
2227 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002228 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002229 sinfo.add_ssrc(stats.local_ssrc);
2230 sinfo.bytes_sent = stats.bytes_sent;
2231 sinfo.packets_sent = stats.packets_sent;
2232 sinfo.packets_lost = stats.packets_lost;
2233 sinfo.fraction_lost = stats.fraction_lost;
2234 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002235 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002236 sinfo.ext_seqnum = stats.ext_seqnum;
2237 sinfo.jitter_ms = stats.jitter_ms;
2238 sinfo.rtt_ms = stats.rtt_ms;
2239 sinfo.audio_level = stats.audio_level;
2240 sinfo.aec_quality_min = stats.aec_quality_min;
2241 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2242 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2243 sinfo.echo_return_loss = stats.echo_return_loss;
2244 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002245 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002246 sinfo.residual_echo_likelihood_recent_max =
2247 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002248 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002249 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 }
2251
solenberg85a04962015-10-27 03:35:21 -07002252 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002253 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002254 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002255 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2256 VoiceReceiverInfo rinfo;
2257 rinfo.add_ssrc(stats.remote_ssrc);
2258 rinfo.bytes_rcvd = stats.bytes_rcvd;
2259 rinfo.packets_rcvd = stats.packets_rcvd;
2260 rinfo.packets_lost = stats.packets_lost;
2261 rinfo.fraction_lost = stats.fraction_lost;
2262 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002263 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002264 rinfo.ext_seqnum = stats.ext_seqnum;
2265 rinfo.jitter_ms = stats.jitter_ms;
2266 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2267 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2268 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2269 rinfo.audio_level = stats.audio_level;
2270 rinfo.expand_rate = stats.expand_rate;
2271 rinfo.speech_expand_rate = stats.speech_expand_rate;
2272 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
2273 rinfo.accelerate_rate = stats.accelerate_rate;
2274 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2275 rinfo.decoding_calls_to_silence_generator =
2276 stats.decoding_calls_to_silence_generator;
2277 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2278 rinfo.decoding_normal = stats.decoding_normal;
2279 rinfo.decoding_plc = stats.decoding_plc;
2280 rinfo.decoding_cng = stats.decoding_cng;
2281 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002282 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002283 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2284 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002285 }
2286
hbos1acfbd22016-11-17 23:43:29 -08002287 // Get codec info
2288 for (const AudioCodec& codec : send_codecs_) {
2289 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2290 info->send_codecs.insert(
2291 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2292 }
2293 for (const AudioCodec& codec : recv_codecs_) {
2294 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2295 info->receive_codecs.insert(
2296 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2297 }
2298
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002299 return true;
2300}
2301
Tommif888bb52015-12-12 01:37:01 +01002302void WebRtcVoiceMediaChannel::SetRawAudioSink(
2303 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002304 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002305 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002306 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2307 << " " << (sink ? "(ptr)" : "NULL");
2308 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002309 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002310 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002311 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002312 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002313 }
2314 default_sink_ = std::move(sink);
2315 return;
2316 }
Tommif888bb52015-12-12 01:37:01 +01002317 const auto it = recv_streams_.find(ssrc);
2318 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002319 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002320 return;
2321 }
deadbeef2d110be2016-01-13 12:00:26 -08002322 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002323}
2324
hbos8d609f62017-04-10 07:39:05 -07002325std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2326 uint32_t ssrc) const {
2327 auto it = recv_streams_.find(ssrc);
2328 RTC_DCHECK(it != recv_streams_.end())
2329 << "Attempting to get contributing sources for SSRC:" << ssrc
2330 << " which doesn't exist.";
2331 return it->second->GetSources();
2332}
2333
Peter Boström0c4e06b2015-10-07 12:23:21 +02002334int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002336 const auto it = recv_streams_.find(ssrc);
2337 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002338 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002339 }
solenberg1ac56142015-10-13 03:58:19 -07002340 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002341}
2342
Peter Boström0c4e06b2015-10-07 12:23:21 +02002343int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002344 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002345 const auto it = send_streams_.find(ssrc);
2346 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002347 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002348 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002349 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350}
solenberg2100c0b2017-03-01 11:29:29 -08002351
2352bool WebRtcVoiceMediaChannel::
2353 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2354 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2355 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2356 unsignaled_recv_ssrcs_.end(),
2357 ssrc);
2358 if (it != unsignaled_recv_ssrcs_.end()) {
2359 unsignaled_recv_ssrcs_.erase(it);
2360 return true;
2361 }
2362 return false;
2363}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002364} // namespace cricket
2365
2366#endif // HAVE_WEBRTC_VOICE