blob: 1f197a33e8d4b7261bf52531e686b4e5598e93d9 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
henrike@webrtc.org28e20752013-07-10 00:45:36 +000011#ifdef HAVE_WEBRTC_VOICE
12
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010013#include "webrtc/media/engine/webrtcvoiceengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
15#include <algorithm>
16#include <cstdio>
ossuc54071d2016-08-17 02:45:41 -070017#include <functional>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018#include <string>
19#include <vector>
20
kjellandera69d9732016-08-31 07:33:05 -070021#include "webrtc/api/call/audio_sink.h"
tfarina5237aaf2015-11-10 23:44:30 -080022#include "webrtc/base/arraysize.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000023#include "webrtc/base/base64.h"
24#include "webrtc/base/byteorder.h"
kwiberg4485ffb2016-04-26 08:14:39 -070025#include "webrtc/base/constructormagic.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000026#include "webrtc/base/helpers.h"
27#include "webrtc/base/logging.h"
solenberg347ec5c2016-09-23 04:21:47 -070028#include "webrtc/base/race_checker.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000029#include "webrtc/base/stringencode.h"
30#include "webrtc/base/stringutils.h"
Peter Boströmca8b4042016-03-08 14:24:13 -080031#include "webrtc/base/trace_event.h"
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080032#include "webrtc/media/base/audiosource.h"
kjellanderf4752772016-03-02 05:42:30 -080033#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080034#include "webrtc/media/base/streamparams.h"
solenberg9a5f032222017-03-15 06:14:12 -070035#include "webrtc/media/engine/adm_helpers.h"
solenberg76377c52017-02-21 00:54:31 -080036#include "webrtc/media/engine/apm_helpers.h"
ossuc54071d2016-08-17 02:45:41 -070037#include "webrtc/media/engine/payload_type_mapper.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010038#include "webrtc/media/engine/webrtcmediaengine.h"
39#include "webrtc/media/engine/webrtcvoe.h"
aleloi10111bc2016-11-17 06:48:48 -080040#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
aleloi048cbdd2017-05-29 02:56:27 -070041#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010043#include "webrtc/system_wrappers/include/field_trial.h"
solenberg2100c0b2017-03-01 11:29:29 -080044#include "webrtc/system_wrappers/include/metrics.h"
solenbergbd138382015-11-20 16:08:07 -080045#include "webrtc/system_wrappers/include/trace.h"
solenberg76377c52017-02-21 00:54:31 -080046#include "webrtc/voice_engine/transmit_mixer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048namespace cricket {
solenbergd97ec302015-10-07 01:40:33 -070049namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050
solenberg418b7d32017-06-13 00:38:27 -070051constexpr size_t kMaxUnsignaledRecvStreams = 4;
solenberg2100c0b2017-03-01 11:29:29 -080052
solenbergbd138382015-11-20 16:08:07 -080053const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
54 webrtc::kTraceWarning | webrtc::kTraceError |
55 webrtc::kTraceCritical;
56const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
57 webrtc::kTraceInfo;
58
solenberg971cab02016-06-14 10:02:41 -070059constexpr int kNackRtpHistoryMs = 5000;
minyue@webrtc.org2dc6f312014-10-31 05:33:10 +000060
peah1bcfce52016-08-26 07:16:04 -070061// Check to verify that the define for the intelligibility enhancer is properly
62// set.
63#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
64 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \
65 WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
66#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
67#endif
68
ossu20a4b3f2017-04-27 02:08:52 -070069// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
minyue10cbb462016-11-07 09:29:22 -080070const int kOpusMinBitrateBps = 6000;
ossu20a4b3f2017-04-27 02:08:52 -070071const int kOpusBitrateFbBps = 32000;
deadbeef80346142016-04-27 14:17:10 -070072
wu@webrtc.orgde305012013-10-31 15:40:38 +000073// Default audio dscp value.
74// See http://tools.ietf.org/html/rfc2474 for details.
75// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
solenbergd97ec302015-10-07 01:40:33 -070076const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000077
Fredrik Solenbergb5727682015-12-04 15:22:19 +010078// Constants from voice_engine_defines.h.
79const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
80const int kMaxTelephoneEventCode = 255;
Fredrik Solenbergb5727682015-12-04 15:22:19 +010081
solenberg31642aa2016-03-14 08:00:37 -070082const int kMinPayloadType = 0;
83const int kMaxPayloadType = 127;
84
deadbeef884f5852016-01-15 09:20:04 -080085class ProxySink : public webrtc::AudioSinkInterface {
86 public:
87 ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
88
89 void OnData(const Data& audio) override { sink_->OnData(audio); }
90
91 private:
92 webrtc::AudioSinkInterface* sink_;
93};
94
solenberg0b675462015-10-09 01:37:09 -070095bool ValidateStreamParams(const StreamParams& sp) {
96 if (sp.ssrcs.empty()) {
97 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
98 return false;
99 }
100 if (sp.ssrcs.size() > 1) {
101 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
102 return false;
103 }
104 return true;
105}
106
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107// Dumps an AudioCodec in RFC 2327-ish format.
solenbergd97ec302015-10-07 01:40:33 -0700108std::string ToString(const AudioCodec& codec) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109 std::stringstream ss;
ossu20a4b3f2017-04-27 02:08:52 -0700110 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
111 if (!codec.params.empty()) {
112 ss << " {";
113 for (const auto& param : codec.params) {
114 ss << " " << param.first << "=" << param.second;
115 }
116 ss << " }";
117 }
118 ss << " (" << codec.id << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 return ss.str();
120}
Minyue Li7100dcd2015-03-27 05:05:59 +0100121
solenbergd97ec302015-10-07 01:40:33 -0700122bool IsCodec(const AudioCodec& codec, const char* ref_name) {
Minyue Li7100dcd2015-03-27 05:05:59 +0100123 return (_stricmp(codec.name.c_str(), ref_name) == 0);
124}
125
solenbergd97ec302015-10-07 01:40:33 -0700126bool FindCodec(const std::vector<AudioCodec>& codecs,
solenberg26c8c912015-11-27 04:00:25 -0800127 const AudioCodec& codec,
128 AudioCodec* found_codec) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200129 for (const AudioCodec& c : codecs) {
130 if (c.Matches(codec)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 if (found_codec != NULL) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200132 *found_codec = c;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 }
134 return true;
135 }
136 }
137 return false;
138}
wu@webrtc.org1d1ffc92013-10-16 18:12:02 +0000139
solenberg0b675462015-10-09 01:37:09 -0700140bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
141 if (codecs.empty()) {
142 return true;
143 }
144 std::vector<int> payload_types;
145 for (const AudioCodec& codec : codecs) {
146 payload_types.push_back(codec.id);
147 }
148 std::sort(payload_types.begin(), payload_types.end());
149 auto it = std::unique(payload_types.begin(), payload_types.end());
150 return it == payload_types.end();
151}
152
minyue6b825df2016-10-31 04:08:32 -0700153rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
154 const AudioOptions& options) {
155 if (options.audio_network_adaptor && *options.audio_network_adaptor &&
156 options.audio_network_adaptor_config) {
157 // Turn on audio network adaptor only when |options_.audio_network_adaptor|
158 // equals true and |options_.audio_network_adaptor_config| has a value.
159 return options.audio_network_adaptor_config;
160 }
161 return rtc::Optional<std::string>();
162}
163
gyzhou95aa9642016-12-13 14:06:26 -0800164webrtc::AudioState::Config MakeAudioStateConfig(
165 VoEWrapper* voe_wrapper,
166 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
solenberg566ef242015-11-06 15:34:49 -0800167 webrtc::AudioState::Config config;
168 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800169 if (audio_mixer) {
170 config.audio_mixer = audio_mixer;
171 } else {
172 config.audio_mixer = webrtc::AudioMixerImpl::Create();
173 }
solenberg566ef242015-11-06 15:34:49 -0800174 return config;
175}
176
deadbeefe702b302017-02-04 12:09:01 -0800177// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
178// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700179rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800180 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700181 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800182 // If application-configured bitrate is set, take minimum of that and SDP
183 // bitrate.
184 const int bps = rtp_max_bitrate_bps
185 ? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
186 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700187 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700188 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700189 }
minyue7a973442016-10-20 03:27:12 -0700190
ossu20a4b3f2017-04-27 02:08:52 -0700191 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700192 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
193 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
194 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700195 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700196 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700197 << ", requires at least " << spec.info.min_bitrate_bps
198 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700199 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700200 }
ossu20a4b3f2017-04-27 02:08:52 -0700201
202 if (spec.info.HasFixedBitrate()) {
203 return rtc::Optional<int>(spec.info.default_bitrate_bps);
204 } else {
205 // If codec is multi-rate then just set the bitrate.
206 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
207 }
solenberg971cab02016-06-14 10:02:41 -0700208}
209
solenberg76377c52017-02-21 00:54:31 -0800210} // namespace
solenberg971cab02016-06-14 10:02:41 -0700211
ossu29b1a8d2016-06-13 07:34:51 -0700212WebRtcVoiceEngine::WebRtcVoiceEngine(
213 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700214 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800215 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
216 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer)
ossueb1fde42017-05-02 06:46:30 -0700217 : WebRtcVoiceEngine(adm,
218 encoder_factory,
219 decoder_factory,
220 audio_mixer,
221 new VoEWrapper()) {
gyzhou95aa9642016-12-13 14:06:26 -0800222 audio_state_ =
223 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer));
solenberg26c8c912015-11-27 04:00:25 -0800224}
225
ossu29b1a8d2016-06-13 07:34:51 -0700226WebRtcVoiceEngine::WebRtcVoiceEngine(
227 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700228 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700229 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800230 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
ossu29b1a8d2016-06-13 07:34:51 -0700231 VoEWrapper* voe_wrapper)
aleloi048cbdd2017-05-29 02:56:27 -0700232 : low_priority_worker_queue_("rtc-low-prio", rtc::TaskQueue::Priority::LOW),
233 adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700234 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700235 decoder_factory_(decoder_factory),
236 voe_wrapper_(voe_wrapper) {
solenberg26c8c912015-11-27 04:00:25 -0800237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700238 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
239 RTC_DCHECK(voe_wrapper);
ossuc54071d2016-08-17 02:45:41 -0700240 RTC_DCHECK(decoder_factory);
solenberg26c8c912015-11-27 04:00:25 -0800241
242 signal_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800243
ossueb1fde42017-05-02 06:46:30 -0700244 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700245 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700246 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700247 for (const AudioCodec& codec : send_codecs_) {
248 LOG(LS_INFO) << ToString(codec);
249 }
250
251 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700252 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700253 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700254 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000255 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000256
solenberg88499ec2016-09-07 07:34:41 -0700257 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000258
solenbergff976312016-03-30 23:28:51 -0700259 // Temporarily turn logging level up for the Init() call.
260 webrtc::Trace::SetTraceCallback(this);
solenbergbd138382015-11-20 16:08:07 -0800261 webrtc::Trace::set_level_filter(kElevatedTraceFilter);
solenberg2515af22015-12-02 06:19:36 -0800262 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
ossu29b1a8d2016-06-13 07:34:51 -0700263 RTC_CHECK_EQ(0, voe_wrapper_->base()->Init(adm_.get(), nullptr,
264 decoder_factory_));
solenbergbd138382015-11-20 16:08:07 -0800265 webrtc::Trace::set_level_filter(kDefaultTraceFilter);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000266
solenbergff976312016-03-30 23:28:51 -0700267 // No ADM supplied? Get the default one from VoE.
268 if (!adm_) {
269 adm_ = voe_wrapper_->base()->audio_device_module();
270 }
271 RTC_DCHECK(adm_);
272
solenberg059fb442016-10-26 05:12:24 -0700273 apm_ = voe_wrapper_->base()->audio_processing();
274 RTC_DCHECK(apm_);
275
solenberg76377c52017-02-21 00:54:31 -0800276 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
277 RTC_DCHECK(transmit_mixer_);
278
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000279 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800280 // calling ApplyOptions or the default will be overwritten.
solenberg76377c52017-02-21 00:54:31 -0800281 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm_);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000282
solenberg0f7d2932016-01-15 01:40:39 -0800283 // Set default engine options.
284 {
285 AudioOptions options;
286 options.echo_cancellation = rtc::Optional<bool>(true);
287 options.auto_gain_control = rtc::Optional<bool>(true);
288 options.noise_suppression = rtc::Optional<bool>(true);
289 options.highpass_filter = rtc::Optional<bool>(true);
290 options.stereo_swapping = rtc::Optional<bool>(false);
291 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
292 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
293 options.typing_detection = rtc::Optional<bool>(true);
294 options.adjust_agc_delta = rtc::Optional<int>(0);
295 options.experimental_agc = rtc::Optional<bool>(false);
296 options.extended_filter_aec = rtc::Optional<bool>(false);
297 options.delay_agnostic_aec = rtc::Optional<bool>(false);
298 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700299 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700300 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800301 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700302 bool error = ApplyOptions(options);
303 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000304 }
305
solenberg9a5f032222017-03-15 06:14:12 -0700306 // Set default audio devices.
307#if !defined(WEBRTC_IOS)
308 webrtc::adm_helpers::SetRecordingDevice(adm_);
309 apm()->Initialize();
310 webrtc::adm_helpers::SetPlayoutDevice(adm_);
311#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000312}
313
solenbergff976312016-03-30 23:28:51 -0700314WebRtcVoiceEngine::~WebRtcVoiceEngine() {
solenberg566ef242015-11-06 15:34:49 -0800315 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700316 LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000317 StopAecDump();
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000318 voe_wrapper_->base()->Terminate();
solenbergff976312016-03-30 23:28:51 -0700319 webrtc::Trace::SetTraceCallback(nullptr);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000320}
321
solenberg566ef242015-11-06 15:34:49 -0800322rtc::scoped_refptr<webrtc::AudioState>
323 WebRtcVoiceEngine::GetAudioState() const {
324 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
325 return audio_state_;
326}
327
nisse51542be2016-02-12 02:27:06 -0800328VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
329 webrtc::Call* call,
330 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200331 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800332 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800333 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000334}
335
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000336bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800337 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700338 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800339 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800340
peah8a8ebd92017-05-22 15:48:47 -0700341 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000342 // kEcConference is AEC with high suppression.
343 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700344 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000345 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700346 << *options.aecm_generate_comfort_noise
347 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000348 }
349
kjellanderfcfc8042016-01-14 11:01:09 -0800350#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700351 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100352 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700353 options.extended_filter_aec = rtc::Optional<bool>(false);
354 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000355#elif defined(ANDROID)
356 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100357 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000358#endif
359
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100360 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
361 // where the feature is not supported.
362 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800363#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700364 if (options.delay_agnostic_aec) {
365 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100366 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100367 options.echo_cancellation = rtc::Optional<bool>(true);
368 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100369 ec_mode = webrtc::kEcConference;
370 }
371 }
372#endif
373
peah8a8ebd92017-05-22 15:48:47 -0700374// Set and adjust noise suppressor options.
375#if defined(WEBRTC_IOS)
376 // On iOS, VPIO provides built-in NS.
377 options.noise_suppression = rtc::Optional<bool>(false);
378 options.typing_detection = rtc::Optional<bool>(false);
379 options.experimental_ns = rtc::Optional<bool>(false);
380 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
381#elif defined(ANDROID)
382 options.typing_detection = rtc::Optional<bool>(false);
383 options.experimental_ns = rtc::Optional<bool>(false);
384#endif
385
386// Set and adjust gain control options.
387#if defined(WEBRTC_IOS)
388 // On iOS, VPIO provides built-in AGC.
389 options.auto_gain_control = rtc::Optional<bool>(false);
390 options.experimental_agc = rtc::Optional<bool>(false);
391 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
392#elif defined(ANDROID)
393 options.experimental_agc = rtc::Optional<bool>(false);
394#endif
395
396#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
397 // 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).
398 if (webrtc::field_trial::IsEnabled(
399 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
400 options.auto_gain_control = rtc::Optional<bool>(false);
401 LOG(LS_INFO) << "Disable AGC according to field trial.";
402 if (!(options.noise_suppression.value_or(false) or
403 options.echo_cancellation.value_or(false))) {
404 // If possible, turn off the high-pass filter.
405 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
406 options.highpass_filter = rtc::Optional<bool>(false);
407 }
408 }
409#endif
410
peah1bcfce52016-08-26 07:16:04 -0700411#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
412 // Hardcode the intelligibility enhancer to be off.
413 options.intelligibility_enhancer = rtc::Optional<bool>(false);
414#endif
415
kwiberg102c6a62015-10-30 02:47:38 -0700416 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000417 // Check if platform supports built-in EC. Currently only supported on
418 // Android and in combination with Java based audio layer.
419 // TODO(henrika): investigate possibility to support built-in EC also
420 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700421 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200422 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200423 // Built-in EC exists on this device and use_delay_agnostic_aec is not
424 // overriding it. Enable/Disable it according to the echo_cancellation
425 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200426 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700427 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700428 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200429 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100430 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000431 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100432 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000433 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
434 }
435 }
solenberg76377c52017-02-21 00:54:31 -0800436 webrtc::apm_helpers::SetEcStatus(
437 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000438#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800439 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000440#endif
441 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700442 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800443 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000444 }
445 }
446
kwiberg102c6a62015-10-30 02:47:38 -0700447 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700448 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
449 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700450 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700451 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200452 // Disable internal software AGC if built-in AGC is enabled,
453 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100454 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200455 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
456 }
457 }
solenberg22818a52017-03-16 01:20:23 -0700458 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000459 }
460
kwiberg102c6a62015-10-30 02:47:38 -0700461 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800462 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000463 // Override default_agc_config_. Generally, an unset option means "leave
464 // the VoE bits alone" in this function, so we want whatever is set to be
465 // stored as the new "default". If we didn't, then setting e.g.
466 // tx_agc_target_dbov would reset digital compression gain and limiter
467 // settings.
468 // Also, if we don't update default_agc_config_, then adjust_agc_delta
469 // would be an offset from the original values, and not whatever was set
470 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700471 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
472 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000473 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700474 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000475 default_agc_config_.digitalCompressionGaindB);
476 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700477 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800478
479 webrtc::AgcConfig config = default_agc_config_;
480 if (options.adjust_agc_delta) {
481 config.targetLeveldBOv -= *options.adjust_agc_delta;
482 LOG(LS_INFO) << "Adjusting AGC level from default -"
483 << default_agc_config_.targetLeveldBOv << "dB to -"
484 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000485 }
solenberg76377c52017-02-21 00:54:31 -0800486 webrtc::apm_helpers::SetAgcConfig(apm_, config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000487 }
488
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700489 if (options.intelligibility_enhancer) {
490 intelligibility_enhancer_ = options.intelligibility_enhancer;
491 }
492 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
493 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
494 options.noise_suppression = intelligibility_enhancer_;
495 }
496
kwiberg102c6a62015-10-30 02:47:38 -0700497 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700498 if (adm()->BuiltInNSIsAvailable()) {
499 bool builtin_ns =
500 *options.noise_suppression &&
501 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
502 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200503 // Disable internal software NS if built-in NS is enabled,
504 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100505 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200506 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
507 }
508 }
solenberg76377c52017-02-21 00:54:31 -0800509 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000510 }
511
kwiberg102c6a62015-10-30 02:47:38 -0700512 if (options.stereo_swapping) {
513 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800514 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000515 }
516
kwiberg102c6a62015-10-30 02:47:38 -0700517 if (options.audio_jitter_buffer_max_packets) {
518 LOG(LS_INFO) << "NetEq capacity is "
519 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700520 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
521 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200522 }
kwiberg102c6a62015-10-30 02:47:38 -0700523 if (options.audio_jitter_buffer_fast_accelerate) {
524 LOG(LS_INFO) << "NetEq fast mode? "
525 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700526 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
527 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200528 }
529
kwiberg102c6a62015-10-30 02:47:38 -0700530 if (options.typing_detection) {
531 LOG(LS_INFO) << "Typing detection is enabled? "
532 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800533 webrtc::apm_helpers::SetTypingDetectionStatus(
534 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000535 }
536
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000537 webrtc::Config config;
538
kwiberg102c6a62015-10-30 02:47:38 -0700539 if (options.delay_agnostic_aec)
540 delay_agnostic_aec_ = options.delay_agnostic_aec;
541 if (delay_agnostic_aec_) {
542 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700543 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700544 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100545 }
546
kwiberg102c6a62015-10-30 02:47:38 -0700547 if (options.extended_filter_aec) {
548 extended_filter_aec_ = options.extended_filter_aec;
549 }
550 if (extended_filter_aec_) {
551 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200552 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700553 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000554 }
555
kwiberg102c6a62015-10-30 02:47:38 -0700556 if (options.experimental_ns) {
557 experimental_ns_ = options.experimental_ns;
558 }
559 if (experimental_ns_) {
560 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000561 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700562 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000563 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000564
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700565 if (intelligibility_enhancer_) {
566 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
567 << *intelligibility_enhancer_;
568 config.Set<webrtc::Intelligibility>(
569 new webrtc::Intelligibility(*intelligibility_enhancer_));
570 }
571
peaha3333bf2016-06-30 00:02:34 -0700572 if (options.level_control) {
573 level_control_ = options.level_control;
574 }
575
576 LOG(LS_INFO) << "Level control: "
577 << (!!level_control_ ? *level_control_ : -1);
578 if (level_control_) {
peah64d6ff72016-11-21 06:28:14 -0800579 apm_config_.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700580 if (options.level_control_initial_peak_level_dbfs) {
peah64d6ff72016-11-21 06:28:14 -0800581 apm_config_.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700582 *options.level_control_initial_peak_level_dbfs;
583 }
peaha3333bf2016-06-30 00:02:34 -0700584 }
585
peah8271d042016-11-22 07:24:52 -0800586 if (options.highpass_filter) {
587 apm_config_.high_pass_filter.enabled = *options.highpass_filter;
588 }
589
ivoc4ca18692017-02-10 05:11:09 -0800590 if (options.residual_echo_detector) {
591 apm_config_.residual_echo_detector.enabled =
592 *options.residual_echo_detector;
593 }
594
solenberg059fb442016-10-26 05:12:24 -0700595 apm()->SetExtraOptions(config);
peah64d6ff72016-11-21 06:28:14 -0800596 apm()->ApplyConfig(apm_config_);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000597
kwiberg102c6a62015-10-30 02:47:38 -0700598 if (options.recording_sample_rate) {
599 LOG(LS_INFO) << "Recording sample rate is "
600 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700601 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700602 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000603 }
604 }
605
kwiberg102c6a62015-10-30 02:47:38 -0700606 if (options.playout_sample_rate) {
607 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700608 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700609 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000610 }
611 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000612 return true;
613}
614
solenberg796b8f92017-03-01 17:02:23 -0800615// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800617 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800618 int8_t level = transmit_mixer()->AudioLevel();
619 RTC_DCHECK_LE(0, level);
620 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621}
622
ossudedfd282016-06-14 07:12:39 -0700623const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
624 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700625 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700626}
627
628const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800629 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700630 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631}
632
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100633RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800634 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100635 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100636 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700637 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
638 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800639 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700640 capabilities.header_extensions.push_back(webrtc::RtpExtension(
641 webrtc::RtpExtension::kTransportSequenceNumberUri,
642 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800643 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100644 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645}
646
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800648 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649 return voe_wrapper_->error();
650}
651
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
653 int length) {
solenberg566ef242015-11-06 15:34:49 -0800654 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000655 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000657 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000659 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000661 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000663 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664
solenberg72e29d22016-03-08 06:35:16 -0800665 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 if (length < 72) {
667 std::string msg(trace, length);
668 LOG(LS_ERROR) << "Malformed webrtc log message: ";
669 LOG_V(sev) << msg;
670 } else {
671 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200672 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 }
674}
675
solenberg63b34542015-09-29 06:06:31 -0700676void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800677 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
678 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 channels_.push_back(channel);
680}
681
solenberg63b34542015-09-29 06:06:31 -0700682void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800683 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700684 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800685 RTC_DCHECK(it != channels_.end());
686 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687}
688
ivocd66b44d2016-01-15 03:06:36 -0800689bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
690 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800691 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700692 auto aec_dump = webrtc::AecDumpFactory::Create(file, max_size_bytes,
693 &low_priority_worker_queue_);
694 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000695 return false;
696 }
aleloi048cbdd2017-05-29 02:56:27 -0700697 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000698 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000699}
700
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000701void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800702 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700703
704 auto aec_dump =
705 webrtc::AecDumpFactory::Create(filename, -1, &low_priority_worker_queue_);
706 if (aec_dump) {
707 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 }
709}
710
711void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800712 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700713 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000714}
715
solenberg0a617e22015-10-20 15:49:38 -0700716int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800717 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700718 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000719}
720
solenberg5b5129a2016-04-08 05:35:48 -0700721webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
722 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
723 RTC_DCHECK(adm_);
724 return adm_;
725}
726
solenberg059fb442016-10-26 05:12:24 -0700727webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
728 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
729 RTC_DCHECK(apm_);
730 return apm_;
731}
732
solenberg76377c52017-02-21 00:54:31 -0800733webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
734 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
735 RTC_DCHECK(transmit_mixer_);
736 return transmit_mixer_;
737}
738
ossu20a4b3f2017-04-27 02:08:52 -0700739AudioCodecs WebRtcVoiceEngine::CollectCodecs(
740 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700741 PayloadTypeMapper mapper;
742 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700743
solenberg2779bab2016-11-17 04:45:19 -0800744 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700745 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
746 { 16000, false },
747 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800748 // Only generate telephone-event payload types for these clockrates:
749 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
750 { 16000, false },
751 { 32000, false },
752 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700753
ossu9def8002017-02-09 05:14:32 -0800754 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
755 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700756 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800757 if (opt_codec) {
758 if (out) {
759 out->push_back(*opt_codec);
760 }
761 } else {
ossuc54071d2016-08-17 02:45:41 -0700762 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700763 }
764
ossu9def8002017-02-09 05:14:32 -0800765 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700766 };
767
ossud4e9f622016-08-18 02:01:17 -0700768 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800769 // We need to do some extra stuff before adding the main codecs to out.
770 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
771 if (opt_codec) {
772 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700773 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800774 codec.AddFeedbackParam(
775 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
776 }
777
ossua1a040a2017-04-06 10:03:21 -0700778 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800779 // Generate a CN entry if the decoder allows it and we support the
780 // clockrate.
781 auto cn = generate_cn.find(spec.format.clockrate_hz);
782 if (cn != generate_cn.end()) {
783 cn->second = true;
784 }
785 }
786
787 // Generate a telephone-event entry if we support the clockrate.
788 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
789 if (dtmf != generate_dtmf.end()) {
790 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700791 }
ossu9def8002017-02-09 05:14:32 -0800792
793 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700794 }
795 }
796
solenberg2779bab2016-11-17 04:45:19 -0800797 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700798 for (const auto& cn : generate_cn) {
799 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800800 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700801 }
802 }
803
solenberg2779bab2016-11-17 04:45:19 -0800804 // Add telephone-event codecs last.
805 for (const auto& dtmf : generate_dtmf) {
806 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800807 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800808 }
809 }
ossuc54071d2016-08-17 02:45:41 -0700810
811 return out;
812}
813
solenbergc96df772015-10-21 13:01:53 -0700814class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800815 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000816 public:
minyue7a973442016-10-20 03:27:12 -0700817 WebRtcAudioSendStream(
818 int ch,
819 webrtc::AudioTransport* voe_audio_transport,
820 uint32_t ssrc,
821 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700822 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
823 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700824 const std::vector<webrtc::RtpExtension>& extensions,
825 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700826 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700827 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700828 webrtc::Transport* send_transport,
829 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800830 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800831 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700832 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800833 send_side_bwe_with_overhead_(
834 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700835 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700836 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700837 RTC_DCHECK_GE(ch, 0);
838 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
839 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700840 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700841 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800842 config_.rtp.ssrc = ssrc;
843 config_.rtp.c_name = c_name;
844 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700845 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700846 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700847 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800848 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700849
850 if (send_codec_spec) {
851 UpdateSendCodecSpec(*send_codec_spec);
852 }
853
854 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700855 }
solenberg3a941542015-11-16 07:34:50 -0800856
solenbergc96df772015-10-21 13:01:53 -0700857 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800858 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800859 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700860 call_->DestroyAudioSendStream(stream_);
861 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000862
ossu20a4b3f2017-04-27 02:08:52 -0700863 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700864 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700865 UpdateSendCodecSpec(send_codec_spec);
866 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700867 }
868
ossu20a4b3f2017-04-27 02:08:52 -0700869 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800870 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800871 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700872 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800873 }
874
ossu20a4b3f2017-04-27 02:08:52 -0700875 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700876 const rtc::Optional<std::string>& audio_network_adaptor_config) {
877 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
878 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
879 return;
880 }
881 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700882 UpdateAllowedBitrateRange();
883 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700884 }
885
minyue7a973442016-10-20 03:27:12 -0700886 bool SetMaxSendBitrate(int bps) {
887 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700888 RTC_DCHECK(config_.send_codec_spec);
889 RTC_DCHECK(audio_codec_spec_);
890 auto send_rate = ComputeSendBitrate(
891 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
892
minyue7a973442016-10-20 03:27:12 -0700893 if (!send_rate) {
894 return false;
895 }
896
897 max_send_bitrate_bps_ = bps;
898
ossu20a4b3f2017-04-27 02:08:52 -0700899 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
900 config_.send_codec_spec->target_bitrate_bps = send_rate;
901 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700902 }
903 return true;
904 }
905
solenbergffbbcac2016-11-17 05:25:37 -0800906 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
907 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100908 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
909 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800910 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
911 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100912 }
913
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800914 void SetSend(bool send) {
915 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
916 send_ = send;
917 UpdateSendState();
918 }
919
solenberg94218532016-06-16 10:53:22 -0700920 void SetMuted(bool muted) {
921 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
922 RTC_DCHECK(stream_);
923 stream_->SetMuted(muted);
924 muted_ = muted;
925 }
926
927 bool muted() const {
928 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
929 return muted_;
930 }
931
solenberg3a941542015-11-16 07:34:50 -0800932 webrtc::AudioSendStream::Stats GetStats() const {
933 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
934 RTC_DCHECK(stream_);
935 return stream_->GetStats();
936 }
937
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800938 // Starts the sending by setting ourselves as a sink to the AudioSource to
939 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000940 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000941 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800942 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800943 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800944 RTC_DCHECK(source);
945 if (source_) {
946 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000947 return;
948 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800949 source->SetSink(this);
950 source_ = source;
951 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000952 }
953
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800954 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000955 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000956 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800957 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800958 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800959 if (source_) {
960 source_->SetSink(nullptr);
961 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700962 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800963 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000964 }
965
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800966 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000967 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000968 void OnData(const void* audio_data,
969 int bits_per_sample,
970 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800971 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700972 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -0700973 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -0700974 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -0700975 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
976 bits_per_sample, sample_rate,
977 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000978 }
979
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800980 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000981 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000982 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -0800983 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800984 // Set |source_| to nullptr to make sure no more callback will get into
985 // the source.
986 source_ = nullptr;
987 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000988 }
989
990 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -0700991 int channel() const {
solenberg566ef242015-11-06 15:34:49 -0800992 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -0800993 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -0700994 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000995
skvlade0d46372016-04-07 22:59:22 -0700996 const webrtc::RtpParameters& rtp_parameters() const {
997 return rtp_parameters_;
998 }
999
deadbeeffb2aced2017-01-06 23:05:37 -08001000 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1001 if (rtp_parameters.encodings.size() != 1) {
1002 LOG(LS_ERROR)
1003 << "Attempted to set RtpParameters without exactly one encoding";
1004 return false;
1005 }
1006 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1007 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1008 return false;
1009 }
1010 return true;
1011 }
1012
minyue7a973442016-10-20 03:27:12 -07001013 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001014 if (!ValidateRtpParameters(parameters)) {
1015 return false;
1016 }
ossu20a4b3f2017-04-27 02:08:52 -07001017
1018 rtc::Optional<int> send_rate;
1019 if (audio_codec_spec_) {
1020 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1021 parameters.encodings[0].max_bitrate_bps,
1022 *audio_codec_spec_);
1023 if (!send_rate) {
1024 return false;
1025 }
minyue7a973442016-10-20 03:27:12 -07001026 }
1027
minyuececec102017-03-27 13:04:25 -07001028 const rtc::Optional<int> old_rtp_max_bitrate =
1029 rtp_parameters_.encodings[0].max_bitrate_bps;
1030
skvlade0d46372016-04-07 22:59:22 -07001031 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001032
minyuececec102017-03-27 13:04:25 -07001033 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001034 // Reconfigure AudioSendStream with new bit rate.
1035 if (send_rate) {
1036 config_.send_codec_spec->target_bitrate_bps = send_rate;
1037 }
1038 UpdateAllowedBitrateRange();
1039 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001040 } else {
1041 // parameters.encodings[0].active could have changed.
1042 UpdateSendState();
1043 }
1044 return true;
skvlade0d46372016-04-07 22:59:22 -07001045 }
1046
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001047 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001048 void UpdateSendState() {
1049 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1050 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001051 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1052 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001053 stream_->Start();
1054 } else { // !send || source_ = nullptr
1055 stream_->Stop();
1056 }
1057 }
1058
ossu20a4b3f2017-04-27 02:08:52 -07001059 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001060 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001061 const bool is_opus =
1062 config_.send_codec_spec &&
1063 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1064 kOpusCodecName);
1065 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001066 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001067
1068 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001069 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001070 // meanwhile change the cap to the output of BWE.
1071 config_.max_bitrate_bps =
1072 rtp_parameters_.encodings[0].max_bitrate_bps
1073 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1074 : kOpusBitrateFbBps;
1075
michaelt53fe19d2016-10-18 09:39:22 -07001076 // TODO(mflodman): Keep testing this and set proper values.
1077 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001078 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001079 const int max_packet_size_ms =
1080 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001081
ossu20a4b3f2017-04-27 02:08:52 -07001082 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1083 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001084
ossu20a4b3f2017-04-27 02:08:52 -07001085 int min_overhead_bps =
1086 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001087
ossu20a4b3f2017-04-27 02:08:52 -07001088 // We assume that |config_.max_bitrate_bps| before the next line is
1089 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1090 // it to ensure that, when overhead is deducted, the payload rate
1091 // never goes beyond the limit.
1092 // Note: this also means that if a higher overhead is forced, we
1093 // cannot reach the limit.
1094 // TODO(minyue): Reconsider this when the signaling to BWE is done
1095 // through a dedicated API.
1096 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001097
ossu20a4b3f2017-04-27 02:08:52 -07001098 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1099 // reachable.
1100 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001101 }
michaelt53fe19d2016-10-18 09:39:22 -07001102 }
ossu20a4b3f2017-04-27 02:08:52 -07001103 }
1104
1105 void UpdateSendCodecSpec(
1106 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1107 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1108 config_.rtp.nack.rtp_history_ms =
1109 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1110 config_.send_codec_spec =
1111 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1112 send_codec_spec);
1113 auto info =
1114 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1115 RTC_DCHECK(info);
1116 // If a specific target bitrate has been set for the stream, use that as
1117 // the new default bitrate when computing send bitrate.
1118 if (send_codec_spec.target_bitrate_bps) {
1119 info->default_bitrate_bps = std::max(
1120 info->min_bitrate_bps,
1121 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1122 }
1123
1124 audio_codec_spec_.emplace(
1125 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1126
1127 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1128 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1129 *audio_codec_spec_);
1130
1131 UpdateAllowedBitrateRange();
1132 }
1133
1134 void ReconfigureAudioSendStream() {
1135 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1136 RTC_DCHECK(stream_);
1137 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001138 }
1139
solenberg566ef242015-11-06 15:34:49 -08001140 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001141 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001142 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1143 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001144 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001145 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001146 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1147 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001148 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001149
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001150 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001151 // PeerConnection will make sure invalidating the pointer before the object
1152 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001153 AudioSource* source_ = nullptr;
1154 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001155 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001156 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001157 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001158 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001159
solenbergc96df772015-10-21 13:01:53 -07001160 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1161};
1162
1163class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1164 public:
ossu29b1a8d2016-06-13 07:34:51 -07001165 WebRtcAudioReceiveStream(
1166 int ch,
1167 uint32_t remote_ssrc,
1168 uint32_t local_ssrc,
1169 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001170 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001171 const std::string& sync_group,
1172 const std::vector<webrtc::RtpExtension>& extensions,
1173 webrtc::Call* call,
1174 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001175 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1176 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001177 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001178 RTC_DCHECK_GE(ch, 0);
1179 RTC_DCHECK(call);
1180 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001181 config_.rtp.local_ssrc = local_ssrc;
1182 config_.rtp.transport_cc = use_transport_cc;
1183 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1184 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001185 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001186 config_.voe_channel_id = ch;
1187 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001188 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001189 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001190 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001191 }
solenbergc96df772015-10-21 13:01:53 -07001192
solenberg7add0582015-11-20 09:59:34 -08001193 ~WebRtcAudioReceiveStream() {
1194 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1195 call_->DestroyAudioReceiveStream(stream_);
1196 }
1197
solenberg4a0f7b52016-06-16 13:07:33 -07001198 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001199 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001200 config_.rtp.local_ssrc = local_ssrc;
1201 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001202 }
solenberg8189b022016-06-14 12:13:00 -07001203
1204 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001205 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001206 config_.rtp.transport_cc = use_transport_cc;
1207 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1208 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001209 }
1210
solenberg4a0f7b52016-06-16 13:07:33 -07001211 void RecreateAudioReceiveStream(
1212 const std::vector<webrtc::RtpExtension>& extensions) {
1213 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001214 config_.rtp.extensions = extensions;
1215 RecreateAudioReceiveStream();
1216 }
1217
deadbeefcb383672017-04-26 16:28:42 -07001218 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001219 void RecreateAudioReceiveStream(
1220 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1221 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001222 config_.decoder_map = decoder_map;
1223 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001224 }
1225
solenberg4904fb62017-02-17 12:01:14 -08001226 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1227 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1228 if (config_.sync_group != sync_group) {
1229 config_.sync_group = sync_group;
1230 RecreateAudioReceiveStream();
1231 }
1232 }
1233
solenberg7add0582015-11-20 09:59:34 -08001234 webrtc::AudioReceiveStream::Stats GetStats() const {
1235 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1236 RTC_DCHECK(stream_);
1237 return stream_->GetStats();
1238 }
1239
solenberg796b8f92017-03-01 17:02:23 -08001240 int GetOutputLevel() const {
1241 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1242 RTC_DCHECK(stream_);
1243 return stream_->GetOutputLevel();
1244 }
1245
solenberg7add0582015-11-20 09:59:34 -08001246 int channel() const {
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 return config_.voe_channel_id;
1249 }
solenbergc96df772015-10-21 13:01:53 -07001250
kwiberg686a8ef2016-02-26 03:00:35 -08001251 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001253 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001254 }
1255
solenberg217fb662016-06-17 08:30:54 -07001256 void SetOutputVolume(double volume) {
1257 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1258 stream_->SetGain(volume);
1259 }
1260
aleloi84ef6152016-08-04 05:28:21 -07001261 void SetPlayout(bool playout) {
1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1263 RTC_DCHECK(stream_);
1264 if (playout) {
1265 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1266 stream_->Start();
1267 } else {
1268 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1269 stream_->Stop();
1270 }
aleloi18e0b672016-10-04 02:45:47 -07001271 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001272 }
1273
hbos8d609f62017-04-10 07:39:05 -07001274 std::vector<webrtc::RtpSource> GetSources() {
1275 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1276 RTC_DCHECK(stream_);
1277 return stream_->GetSources();
1278 }
1279
solenbergc96df772015-10-21 13:01:53 -07001280 private:
kwibergd32bf752017-01-19 07:03:59 -08001281 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001282 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1283 if (stream_) {
1284 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001285 }
solenberg7add0582015-11-20 09:59:34 -08001286 stream_ = call_->CreateAudioReceiveStream(config_);
1287 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001288 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001289 }
1290
1291 rtc::ThreadChecker worker_thread_checker_;
1292 webrtc::Call* call_ = nullptr;
1293 webrtc::AudioReceiveStream::Config config_;
1294 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1295 // configuration changes.
1296 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001297 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001298
1299 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001300};
1301
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001302WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001303 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001304 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001305 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001306 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001307 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001308 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001309 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001310 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001311}
1312
1313WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001314 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001315 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001316 // TODO(solenberg): Should be able to delete the streams directly, without
1317 // going through RemoveNnStream(), once stream objects handle
1318 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001319 while (!send_streams_.empty()) {
1320 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001321 }
solenberg7add0582015-11-20 09:59:34 -08001322 while (!recv_streams_.empty()) {
1323 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 }
solenberg0a617e22015-10-20 15:49:38 -07001325 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326}
1327
nisse51542be2016-02-12 02:27:06 -08001328rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1329 return kAudioDscpValue;
1330}
1331
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001332bool WebRtcVoiceMediaChannel::SetSendParameters(
1333 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001334 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001335 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001336 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1337 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001338 // TODO(pthatcher): Refactor this to be more clean now that we have
1339 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001340
1341 if (!SetSendCodecs(params.codecs)) {
1342 return false;
1343 }
1344
solenberg7e4e01a2015-12-02 08:05:01 -08001345 if (!ValidateRtpExtensions(params.extensions)) {
1346 return false;
1347 }
1348 std::vector<webrtc::RtpExtension> filtered_extensions =
1349 FilterRtpExtensions(params.extensions,
1350 webrtc::RtpExtension::IsSupportedForAudio, true);
1351 if (send_rtp_extensions_ != filtered_extensions) {
1352 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001353 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001354 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001355 }
1356 }
1357
deadbeef80346142016-04-27 14:17:10 -07001358 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001359 return false;
1360 }
1361 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001362}
1363
1364bool WebRtcVoiceMediaChannel::SetRecvParameters(
1365 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001366 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001367 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001368 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1369 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001370 // TODO(pthatcher): Refactor this to be more clean now that we have
1371 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001372
1373 if (!SetRecvCodecs(params.codecs)) {
1374 return false;
1375 }
1376
solenberg7e4e01a2015-12-02 08:05:01 -08001377 if (!ValidateRtpExtensions(params.extensions)) {
1378 return false;
1379 }
1380 std::vector<webrtc::RtpExtension> filtered_extensions =
1381 FilterRtpExtensions(params.extensions,
1382 webrtc::RtpExtension::IsSupportedForAudio, false);
1383 if (recv_rtp_extensions_ != filtered_extensions) {
1384 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001385 for (auto& it : recv_streams_) {
1386 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1387 }
1388 }
solenberg7add0582015-11-20 09:59:34 -08001389 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001390}
1391
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001392webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001393 uint32_t ssrc) const {
1394 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1395 auto it = send_streams_.find(ssrc);
1396 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001397 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1398 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001399 return webrtc::RtpParameters();
1400 }
1401
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001402 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1403 // Need to add the common list of codecs to the send stream-specific
1404 // RTP parameters.
1405 for (const AudioCodec& codec : send_codecs_) {
1406 rtp_params.codecs.push_back(codec.ToCodecParameters());
1407 }
1408 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001409}
1410
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001411bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001412 uint32_t ssrc,
1413 const webrtc::RtpParameters& parameters) {
1414 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001415 auto it = send_streams_.find(ssrc);
1416 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001417 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1418 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001419 return false;
1420 }
1421
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001422 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1423 // different order (which should change the send codec).
1424 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1425 if (current_parameters.codecs != parameters.codecs) {
1426 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1427 << "is not currently supported.";
1428 return false;
1429 }
1430
minyue7a973442016-10-20 03:27:12 -07001431 // TODO(minyue): The following legacy actions go into
1432 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1433 // though there are two difference:
1434 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1435 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1436 // |SetSendCodecs|. The outcome should be the same.
1437 // 2. AudioSendStream can be recreated.
1438
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001439 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1440 webrtc::RtpParameters reduced_params = parameters;
1441 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001442 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001443}
1444
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001445webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1446 uint32_t ssrc) const {
1447 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001448 webrtc::RtpParameters rtp_params;
1449 // SSRC of 0 represents the default receive stream.
1450 if (ssrc == 0) {
1451 if (!default_sink_) {
1452 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1453 "unsignaled audio receive stream, but not yet "
1454 "configured to receive such a stream.";
1455 return rtp_params;
1456 }
1457 rtp_params.encodings.emplace_back();
1458 } else {
1459 auto it = recv_streams_.find(ssrc);
1460 if (it == recv_streams_.end()) {
1461 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1462 << "with ssrc " << ssrc << " which doesn't exist.";
1463 return webrtc::RtpParameters();
1464 }
1465 rtp_params.encodings.emplace_back();
1466 // TODO(deadbeef): Return stream-specific parameters.
1467 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001468 }
1469
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001470 for (const AudioCodec& codec : recv_codecs_) {
1471 rtp_params.codecs.push_back(codec.ToCodecParameters());
1472 }
1473 return rtp_params;
1474}
1475
1476bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1477 uint32_t ssrc,
1478 const webrtc::RtpParameters& parameters) {
1479 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001480 // SSRC of 0 represents the default receive stream.
1481 if (ssrc == 0) {
1482 if (!default_sink_) {
1483 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1484 "unsignaled audio receive stream, but not yet "
1485 "configured to receive such a stream.";
1486 return false;
1487 }
1488 } else {
1489 auto it = recv_streams_.find(ssrc);
1490 if (it == recv_streams_.end()) {
1491 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1492 << "with ssrc " << ssrc << " which doesn't exist.";
1493 return false;
1494 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001495 }
1496
1497 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1498 if (current_parameters != parameters) {
1499 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1500 << "unsupported.";
1501 return false;
1502 }
1503 return true;
1504}
1505
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001507 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508 LOG(LS_INFO) << "Setting voice channel options: "
1509 << options.ToString();
1510
1511 // We retain all of the existing options, and apply the given ones
1512 // on top. This means there is no way to "clear" options such that
1513 // they go back to the engine default.
1514 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001515 if (!engine()->ApplyOptions(options_)) {
1516 LOG(LS_WARNING) <<
1517 "Failed to apply engine options during channel SetOptions.";
1518 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519 }
minyue6b825df2016-10-31 04:08:32 -07001520
ossu20a4b3f2017-04-27 02:08:52 -07001521 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001522 GetAudioNetworkAdaptorConfig(options_);
1523 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001524 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001525 }
1526
solenberg76377c52017-02-21 00:54:31 -08001527 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 << options_.ToString();
1529 return true;
1530}
1531
1532bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1533 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001534 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001535
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001537 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001538
1539 if (!VerifyUniquePayloadTypes(codecs)) {
1540 LOG(LS_ERROR) << "Codec payload types overlap.";
1541 return false;
1542 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543
kwibergd32bf752017-01-19 07:03:59 -08001544 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1545 // unless the factory claims to support all decoders.
1546 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1547 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001548 // Log a warning if a codec's payload type is changing. This used to be
1549 // treated as an error. It's abnormal, but not really illegal.
1550 AudioCodec old_codec;
1551 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1552 old_codec.id != codec.id) {
1553 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1554 << codec.id << ", was already mapped to " << old_codec.id
1555 << ")";
1556 }
kwibergd32bf752017-01-19 07:03:59 -08001557 auto format = AudioCodecToSdpAudioFormat(codec);
1558 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1559 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1560 LOG(LS_ERROR) << "Unsupported codec: " << format;
1561 return false;
1562 }
deadbeefcb383672017-04-26 16:28:42 -07001563 // We allow adding new codecs but don't allow changing the payload type of
1564 // codecs that are already configured since we might already be receiving
1565 // packets with that payload type. See RFC3264, Section 8.3.2.
1566 // TODO(deadbeef): Also need to check for clashes with previously mapped
1567 // payload types, and not just currently mapped ones. For example, this
1568 // should be illegal:
1569 // 1. {100: opus/48000/2, 101: ISAC/16000}
1570 // 2. {100: opus/48000/2}
1571 // 3. {100: opus/48000/2, 101: ISAC/32000}
1572 // Though this check really should happen at a higher level, since this
1573 // conflict could happen between audio and video codecs.
1574 auto existing = decoder_map_.find(codec.id);
1575 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1576 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1577 << codec.name << ", but it is already used for "
1578 << existing->second.name;
1579 return false;
1580 }
kwibergd32bf752017-01-19 07:03:59 -08001581 decoder_map.insert({codec.id, std::move(format)});
1582 }
1583
deadbeefcb383672017-04-26 16:28:42 -07001584 if (decoder_map == decoder_map_) {
1585 // There's nothing new to configure.
1586 return true;
1587 }
1588
kwiberg37b8b112016-11-03 02:46:53 -07001589 if (playout_) {
1590 // Receive codecs can not be changed while playing. So we temporarily
1591 // pause playout.
1592 ChangePlayout(false);
1593 }
1594
kwiberg1c07c702017-03-27 07:15:49 -07001595 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001596 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001597 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001598 }
kwibergd32bf752017-01-19 07:03:59 -08001599 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600
kwiberg37b8b112016-11-03 02:46:53 -07001601 if (desired_playout_ && !playout_) {
1602 ChangePlayout(desired_playout_);
1603 }
kwibergd32bf752017-01-19 07:03:59 -08001604 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605}
1606
solenberg72e29d22016-03-08 06:35:16 -08001607// Utility function called from SetSendParameters() to extract current send
1608// codec settings from the given list of codecs (originally from SDP). Both send
1609// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001610bool WebRtcVoiceMediaChannel::SetSendCodecs(
1611 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001612 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001613 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001614 dtmf_payload_freq_ = -1;
1615
1616 // Validate supplied codecs list.
1617 for (const AudioCodec& codec : codecs) {
1618 // TODO(solenberg): Validate more aspects of input - that payload types
1619 // don't overlap, remove redundant/unsupported codecs etc -
1620 // the same way it is done for RtpHeaderExtensions.
1621 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1622 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1623 return false;
1624 }
1625 }
1626
1627 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1628 // case we don't have a DTMF codec with a rate matching the send codec's, or
1629 // if this function returns early.
1630 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001631 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001632 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001633 dtmf_codecs.push_back(codec);
1634 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1635 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1636 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001637 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001638 }
1639 }
1640
ossu20a4b3f2017-04-27 02:08:52 -07001641 // Scan through the list to figure out the codec to use for sending.
1642 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001643 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001644 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1645 for (const AudioCodec& voice_codec : codecs) {
1646 if (!(IsCodec(voice_codec, kCnCodecName) ||
1647 IsCodec(voice_codec, kDtmfCodecName) ||
1648 IsCodec(voice_codec, kRedCodecName))) {
1649 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1650 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001651
ossu20a4b3f2017-04-27 02:08:52 -07001652 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1653 if (!voice_codec_info) {
1654 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001655 continue;
1656 }
1657
ossu20a4b3f2017-04-27 02:08:52 -07001658 send_codec_spec =
1659 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1660 {voice_codec.id, format});
1661 if (voice_codec.bitrate > 0) {
1662 send_codec_spec->target_bitrate_bps =
1663 rtc::Optional<int>(voice_codec.bitrate);
1664 }
1665 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1666 send_codec_spec->nack_enabled = HasNack(voice_codec);
1667 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1668 break;
1669 }
1670 }
1671
1672 if (!send_codec_spec) {
1673 return false;
1674 }
1675
1676 RTC_DCHECK(voice_codec_info);
1677 if (voice_codec_info->allow_comfort_noise) {
1678 // Loop through the codecs list again to find the CN codec.
1679 // TODO(solenberg): Break out into a separate function?
1680 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001681 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001682 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001683 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001684 case 8000:
1685 case 16000:
1686 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001687 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001688 break;
1689 default:
ossu0c4b8492017-03-02 11:03:25 -08001690 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001691 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001692 break;
solenberg72e29d22016-03-08 06:35:16 -08001693 }
solenberg72e29d22016-03-08 06:35:16 -08001694 break;
1695 }
1696 }
solenbergffbbcac2016-11-17 05:25:37 -08001697
1698 // Find the telephone-event PT exactly matching the preferred send codec.
1699 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001700 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001701 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1702 dtmf_payload_freq_ = dtmf_codec.clockrate;
1703 break;
1704 }
1705 }
solenberg72e29d22016-03-08 06:35:16 -08001706 }
1707
solenberg971cab02016-06-14 10:02:41 -07001708 if (send_codec_spec_ != send_codec_spec) {
1709 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001710 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001711 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001712 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001713 }
stefan13f1a0a2016-11-30 07:22:58 -08001714 } else {
1715 // If the codec isn't changing, set the start bitrate to -1 which means
1716 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001717 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001718 }
stefan1ccf73f2017-03-27 03:51:18 -07001719 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001720
solenberg8189b022016-06-14 12:13:00 -07001721 // Check if the transport cc feedback or NACK status has changed on the
1722 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001723 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1724 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001725 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1726 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001727 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1728 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001729 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001730 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1731 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001732 }
1733 }
1734
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001735 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001736 return true;
1737}
1738
aleloi84ef6152016-08-04 05:28:21 -07001739void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001740 desired_playout_ = playout;
1741 return ChangePlayout(desired_playout_);
1742}
1743
1744void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1745 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001746 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001748 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 }
1750
aleloi84ef6152016-08-04 05:28:21 -07001751 for (const auto& kv : recv_streams_) {
1752 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753 }
solenberg1ac56142015-10-13 03:58:19 -07001754 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755}
1756
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001757void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001758 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001760 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761 }
1762
solenbergd53a3f92016-04-14 13:56:37 -07001763 // Apply channel specific options, and initialize the ADM for recording (this
1764 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001765 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001766 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001767
1768 // InitRecording() may return an error if the ADM is already recording.
1769 if (!engine()->adm()->RecordingIsInitialized() &&
1770 !engine()->adm()->Recording()) {
1771 if (engine()->adm()->InitRecording() != 0) {
1772 LOG(LS_WARNING) << "Failed to initialize recording";
1773 }
1774 }
solenberg63b34542015-09-29 06:06:31 -07001775 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001776
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001777 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001778 for (auto& kv : send_streams_) {
1779 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001780 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001781
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783}
1784
Peter Boström0c4e06b2015-10-07 12:23:21 +02001785bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1786 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001787 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001788 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001789 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001790 // TODO(solenberg): The state change should be fully rolled back if any one of
1791 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001792 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001793 return false;
1794 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001795 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001796 return false;
1797 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001798 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001799 return SetOptions(*options);
1800 }
1801 return true;
1802}
1803
solenberg0a617e22015-10-20 15:49:38 -07001804int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1805 int id = engine()->CreateVoEChannel();
1806 if (id == -1) {
1807 LOG_RTCERR0(CreateVoEChannel);
1808 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001809 }
mflodman3d7db262016-04-29 00:57:13 -07001810
solenberg0a617e22015-10-20 15:49:38 -07001811 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001812}
1813
solenberg7add0582015-11-20 09:59:34 -08001814bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001815 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1816 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001817 return false;
1818 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001819 return true;
1820}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001821
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001822bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001823 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001824 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001825 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1826
1827 uint32_t ssrc = sp.first_ssrc();
1828 RTC_DCHECK(0 != ssrc);
1829
1830 if (GetSendChannelId(ssrc) != -1) {
1831 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001832 return false;
1833 }
1834
solenberg0a617e22015-10-20 15:49:38 -07001835 // Create a new channel for sending audio data.
1836 int channel = CreateVoEChannel();
1837 if (channel == -1) {
1838 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001839 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001840
solenbergc96df772015-10-21 13:01:53 -07001841 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001842 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001843 webrtc::AudioTransport* audio_transport =
1844 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001845
minyue6b825df2016-10-31 04:08:32 -07001846 rtc::Optional<std::string> audio_network_adaptor_config =
1847 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001848 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001849 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001850 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001851 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001852 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001853
solenberg4a0f7b52016-06-16 13:07:33 -07001854 // At this point the stream's local SSRC has been updated. If it is the first
1855 // send stream, make sure that all the receive streams are updated with the
1856 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001857 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001858 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001859 for (const auto& kv : recv_streams_) {
1860 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1861 // streams instead, so we can avoid recreating the streams here.
1862 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001863 }
1864 }
1865
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001866 send_streams_[ssrc]->SetSend(send_);
1867 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001868}
1869
Peter Boström0c4e06b2015-10-07 12:23:21 +02001870bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001871 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001872 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001873 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1874
solenbergc96df772015-10-21 13:01:53 -07001875 auto it = send_streams_.find(ssrc);
1876 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001877 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1878 << " which doesn't exist.";
1879 return false;
1880 }
1881
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001882 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001883
solenberg7602aab2016-11-14 11:30:07 -08001884 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1885 // the first active send stream and use that instead, reassociating receive
1886 // streams.
1887
solenberg7add0582015-11-20 09:59:34 -08001888 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001889 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001890 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1891 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001892 delete it->second;
1893 send_streams_.erase(it);
1894 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001895 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001896 }
solenbergc96df772015-10-21 13:01:53 -07001897 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001898 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001899 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001900 return true;
1901}
1902
1903bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001904 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001905 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001906 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1907
solenberg0b675462015-10-09 01:37:09 -07001908 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001909 return false;
1910 }
1911
solenberg7add0582015-11-20 09:59:34 -08001912 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001913 if (ssrc == 0) {
1914 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1915 return false;
1916 }
1917
solenberg2100c0b2017-03-01 11:29:29 -08001918 // If this stream was previously received unsignaled, we promote it, possibly
1919 // recreating the AudioReceiveStream, if sync_label has changed.
1920 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001921 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001922 return true;
solenberg1ac56142015-10-13 03:58:19 -07001923 }
solenberg0b675462015-10-09 01:37:09 -07001924
solenberg7add0582015-11-20 09:59:34 -08001925 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001926 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001927 return false;
1928 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001929
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001931 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001932 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001933 return false;
1934 }
Minyue2013aec2015-05-13 14:14:42 +02001935
stefanba4c0e42016-02-04 04:12:24 -08001936 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001937 ssrc,
1938 new WebRtcAudioReceiveStream(
1939 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1940 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1941 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001942 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001943
solenberg1ac56142015-10-13 03:58:19 -07001944 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001945}
1946
Peter Boström0c4e06b2015-10-07 12:23:21 +02001947bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001948 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001949 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001950 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1951
solenberg7add0582015-11-20 09:59:34 -08001952 const auto it = recv_streams_.find(ssrc);
1953 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001954 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1955 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001956 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001957 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001958
solenberg2100c0b2017-03-01 11:29:29 -08001959 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001960
solenberg7add0582015-11-20 09:59:34 -08001961 const int channel = it->second->channel();
1962
1963 // Clean up and delete the receive stream+channel.
1964 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001965 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001966 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001967 delete it->second;
1968 recv_streams_.erase(it);
1969 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970}
1971
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001972bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
1973 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07001974 auto it = send_streams_.find(ssrc);
1975 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001976 if (source) {
1977 // Return an error if trying to set a valid source with an invalid ssrc.
1978 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001979 return false;
1980 }
1981
1982 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001983 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001984 }
1985
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001986 if (source) {
1987 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07001988 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001989 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07001990 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001991
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001992 return true;
1993}
1994
solenberg796b8f92017-03-01 17:02:23 -08001995// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001996bool WebRtcVoiceMediaChannel::GetActiveStreams(
1997 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08001998 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001999 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002000 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002001 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002002 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002003 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 }
2005 }
2006 return true;
2007}
2008
solenberg796b8f92017-03-01 17:02:23 -08002009// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002010int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002011 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002012 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002013 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002014 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002015 }
2016 return highest;
2017}
2018
solenberg4bac9c52015-10-09 02:32:53 -07002019bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002020 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002021 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002022 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002023 if (ssrc == 0) {
2024 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002025 ssrcs = unsignaled_recv_ssrcs_;
2026 }
2027 for (uint32_t ssrc : ssrcs) {
2028 const auto it = recv_streams_.find(ssrc);
2029 if (it == recv_streams_.end()) {
2030 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2031 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 }
solenberg2100c0b2017-03-01 11:29:29 -08002033 it->second->SetOutputVolume(volume);
2034 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2035 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002036 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037 return true;
2038}
2039
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002041 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042}
2043
solenberg1d63dd02015-12-02 12:35:09 -08002044bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2045 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002046 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002047 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2048 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049 return false;
2050 }
2051
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002052 // Figure out which WebRtcAudioSendStream to send the event on.
2053 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2054 if (it == send_streams_.end()) {
2055 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002056 return false;
2057 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002058 if (event < kMinTelephoneEventCode ||
2059 event > kMaxTelephoneEventCode) {
2060 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002061 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002062 }
solenbergffbbcac2016-11-17 05:25:37 -08002063 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2064 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2065 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066}
2067
wu@webrtc.orga9890802013-12-13 00:21:03 +00002068void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002069 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002070 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002071
mflodman3d7db262016-04-29 00:57:13 -07002072 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2073 packet_time.not_before);
2074 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2075 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2076 packet->cdata(), packet->size(),
2077 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002078 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2079 return;
2080 }
2081
solenberg2100c0b2017-03-01 11:29:29 -08002082 // Create an unsignaled receive stream for this previously not received ssrc.
2083 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002084 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002085 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002086 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002087 return;
2088 }
solenberg2100c0b2017-03-01 11:29:29 -08002089 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2090 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002091
solenberg2100c0b2017-03-01 11:29:29 -08002092 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002093 StreamParams sp;
2094 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002095 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002096 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002097 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002098 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099 }
solenberg2100c0b2017-03-01 11:29:29 -08002100 unsignaled_recv_ssrcs_.push_back(ssrc);
2101 RTC_HISTOGRAM_COUNTS_LINEAR(
2102 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2103 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002104
solenberg2100c0b2017-03-01 11:29:29 -08002105 // Remove oldest unsignaled stream, if we have too many.
2106 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2107 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2108 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2109 << remove_ssrc;
2110 RemoveRecvStream(remove_ssrc);
2111 }
2112 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2113
2114 SetOutputVolume(ssrc, default_recv_volume_);
2115
2116 // The default sink can only be attached to one stream at a time, so we hook
2117 // it up to the *latest* unsignaled stream we've seen, in order to support the
2118 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002119 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002120 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2121 auto it = recv_streams_.find(drop_ssrc);
2122 it->second->SetRawAudioSink(nullptr);
2123 }
mflodman3d7db262016-04-29 00:57:13 -07002124 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2125 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002126 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002127 }
solenberg2100c0b2017-03-01 11:29:29 -08002128
mflodman3d7db262016-04-29 00:57:13 -07002129 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2130 packet->cdata(),
2131 packet->size(),
2132 webrtc_packet_time);
2133 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002134}
2135
wu@webrtc.orga9890802013-12-13 00:21:03 +00002136void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002137 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002138 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002139
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002140 // Forward packet to Call as well.
2141 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2142 packet_time.not_before);
2143 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002144 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145}
2146
Honghai Zhangcc411c02016-03-29 17:27:21 -07002147void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2148 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002149 const rtc::NetworkRoute& network_route) {
2150 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002151}
2152
Peter Boström0c4e06b2015-10-07 12:23:21 +02002153bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002154 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002155 const auto it = send_streams_.find(ssrc);
2156 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002157 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2158 return false;
2159 }
solenberg94218532016-06-16 10:53:22 -07002160 it->second->SetMuted(muted);
2161
2162 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002163 // We set the AGC to mute state only when all the channels are muted.
2164 // This implementation is not ideal, instead we should signal the AGC when
2165 // the mic channel is muted/unmuted. We can't do it today because there
2166 // is no good way to know which stream is mapping to the mic channel.
2167 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002168 for (const auto& kv : send_streams_) {
2169 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002170 }
solenberg059fb442016-10-26 05:12:24 -07002171 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002172
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 return true;
2174}
2175
deadbeef80346142016-04-27 14:17:10 -07002176bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2177 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2178 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002179 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002180 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002181 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2182 success = false;
skvlade0d46372016-04-07 22:59:22 -07002183 }
2184 }
minyue7a973442016-10-20 03:27:12 -07002185 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002186}
2187
skvlad7a43d252016-03-22 15:32:27 -07002188void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2189 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2190 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2191 call_->SignalChannelNetworkState(
2192 webrtc::MediaType::AUDIO,
2193 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2194}
2195
michaelt79e05882016-11-08 02:50:09 -08002196void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2197 int transport_overhead_per_packet) {
2198 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2199 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2200 transport_overhead_per_packet);
2201}
2202
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002203bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002204 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002205 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002206 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002207
solenberg85a04962015-10-27 03:35:21 -07002208 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002209 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002210 for (const auto& stream : send_streams_) {
2211 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002212 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002213 sinfo.add_ssrc(stats.local_ssrc);
2214 sinfo.bytes_sent = stats.bytes_sent;
2215 sinfo.packets_sent = stats.packets_sent;
2216 sinfo.packets_lost = stats.packets_lost;
2217 sinfo.fraction_lost = stats.fraction_lost;
2218 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002219 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002220 sinfo.ext_seqnum = stats.ext_seqnum;
2221 sinfo.jitter_ms = stats.jitter_ms;
2222 sinfo.rtt_ms = stats.rtt_ms;
2223 sinfo.audio_level = stats.audio_level;
2224 sinfo.aec_quality_min = stats.aec_quality_min;
2225 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2226 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2227 sinfo.echo_return_loss = stats.echo_return_loss;
2228 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002229 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002230 sinfo.residual_echo_likelihood_recent_max =
2231 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002232 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002233 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002234 }
2235
solenberg85a04962015-10-27 03:35:21 -07002236 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002237 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002238 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002239 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2240 VoiceReceiverInfo rinfo;
2241 rinfo.add_ssrc(stats.remote_ssrc);
2242 rinfo.bytes_rcvd = stats.bytes_rcvd;
2243 rinfo.packets_rcvd = stats.packets_rcvd;
2244 rinfo.packets_lost = stats.packets_lost;
2245 rinfo.fraction_lost = stats.fraction_lost;
2246 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002247 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002248 rinfo.ext_seqnum = stats.ext_seqnum;
2249 rinfo.jitter_ms = stats.jitter_ms;
2250 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2251 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2252 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2253 rinfo.audio_level = stats.audio_level;
2254 rinfo.expand_rate = stats.expand_rate;
2255 rinfo.speech_expand_rate = stats.speech_expand_rate;
2256 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
2257 rinfo.accelerate_rate = stats.accelerate_rate;
2258 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2259 rinfo.decoding_calls_to_silence_generator =
2260 stats.decoding_calls_to_silence_generator;
2261 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2262 rinfo.decoding_normal = stats.decoding_normal;
2263 rinfo.decoding_plc = stats.decoding_plc;
2264 rinfo.decoding_cng = stats.decoding_cng;
2265 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002266 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002267 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2268 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002269 }
2270
hbos1acfbd22016-11-17 23:43:29 -08002271 // Get codec info
2272 for (const AudioCodec& codec : send_codecs_) {
2273 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2274 info->send_codecs.insert(
2275 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2276 }
2277 for (const AudioCodec& codec : recv_codecs_) {
2278 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2279 info->receive_codecs.insert(
2280 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2281 }
2282
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002283 return true;
2284}
2285
Tommif888bb52015-12-12 01:37:01 +01002286void WebRtcVoiceMediaChannel::SetRawAudioSink(
2287 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002288 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002289 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002290 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2291 << " " << (sink ? "(ptr)" : "NULL");
2292 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002293 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002294 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002295 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002296 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002297 }
2298 default_sink_ = std::move(sink);
2299 return;
2300 }
Tommif888bb52015-12-12 01:37:01 +01002301 const auto it = recv_streams_.find(ssrc);
2302 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002303 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002304 return;
2305 }
deadbeef2d110be2016-01-13 12:00:26 -08002306 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002307}
2308
hbos8d609f62017-04-10 07:39:05 -07002309std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2310 uint32_t ssrc) const {
2311 auto it = recv_streams_.find(ssrc);
2312 RTC_DCHECK(it != recv_streams_.end())
2313 << "Attempting to get contributing sources for SSRC:" << ssrc
2314 << " which doesn't exist.";
2315 return it->second->GetSources();
2316}
2317
Peter Boström0c4e06b2015-10-07 12:23:21 +02002318int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002319 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002320 const auto it = recv_streams_.find(ssrc);
2321 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002322 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002323 }
solenberg1ac56142015-10-13 03:58:19 -07002324 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002325}
2326
Peter Boström0c4e06b2015-10-07 12:23:21 +02002327int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002328 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002329 const auto it = send_streams_.find(ssrc);
2330 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002331 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002332 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002333 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002334}
solenberg2100c0b2017-03-01 11:29:29 -08002335
2336bool WebRtcVoiceMediaChannel::
2337 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2338 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2339 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2340 unsignaled_recv_ssrcs_.end(),
2341 ssrc);
2342 if (it != unsignaled_recv_ssrcs_.end()) {
2343 unsignaled_recv_ssrcs_.erase(it);
2344 return true;
2345 }
2346 return false;
2347}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002348} // namespace cricket
2349
2350#endif // HAVE_WEBRTC_VOICE