blob: d15a2422b1675f47f662e29bb4d466ab07f992fc [file] [log] [blame]
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +00001/*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 * 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.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +000012
ossu264087f2016-04-18 08:07:24 -070013#include <algorithm>
minyuea6f495c2016-10-24 09:19:14 -070014#include <iterator>
Mirko Bonadeie45c6882019-02-16 09:59:29 +010015#include <string>
ossua1a040a2017-04-06 10:03:21 -070016#include <utility>
ossu264087f2016-04-18 08:07:24 -070017
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
Niels Möller2edab4c2018-10-22 09:48:08 +020019#include "absl/strings/match.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
21#include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
Alex Loikoe5b94162019-04-08 17:19:41 +020022#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/audio_coding/codecs/opus/opus_interface.h"
24#include "rtc_base/arraysize.h"
25#include "rtc_base/checks.h"
26#include "rtc_base/logging.h"
27#include "rtc_base/numerics/exp_filter.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010028#include "rtc_base/numerics/safe_conversions.h"
29#include "rtc_base/numerics/safe_minmax.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/string_to_number.h"
Steve Anton10542f22019-01-11 09:11:00 -080031#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "system_wrappers/include/field_trial.h"
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +000033
34namespace webrtc {
35
36namespace {
37
ossua1a040a2017-04-06 10:03:21 -070038// Codec parameters for Opus.
39// draft-spittka-payload-rtp-opus-03
40
41// Recommended bitrates:
42// 8-12 kb/s for NB speech,
43// 16-20 kb/s for WB speech,
44// 28-40 kb/s for FB speech,
45// 48-64 kb/s for FB mono music, and
46// 64-128 kb/s for FB stereo music.
47// The current implementation applies the following values to mono signals,
48// and multiplies them by 2 for stereo.
49constexpr int kOpusBitrateNbBps = 12000;
50constexpr int kOpusBitrateWbBps = 20000;
51constexpr int kOpusBitrateFbBps = 32000;
michaelt54340d82017-01-31 09:06:53 -080052
Karl Wibergeb166972019-05-16 15:14:01 +020053constexpr int kRtpTimestampRateHz = 48000;
ossua1a040a2017-04-06 10:03:21 -070054constexpr int kDefaultMaxPlaybackRate = 48000;
michaelta55f0212017-02-02 07:47:19 -080055
ossua1a040a2017-04-06 10:03:21 -070056// These two lists must be sorted from low to high
michaelta55f0212017-02-02 07:47:19 -080057#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
ossua1a040a2017-04-06 10:03:21 -070058constexpr int kANASupportedFrameLengths[] = {20, 60, 120};
59constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60, 120};
michaelta55f0212017-02-02 07:47:19 -080060#else
ossua1a040a2017-04-06 10:03:21 -070061constexpr int kANASupportedFrameLengths[] = {20, 60};
62constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60};
michaelta55f0212017-02-02 07:47:19 -080063#endif
henrik.lundin@webrtc.org478cedc2015-01-27 18:24:45 +000064
minyue7e304322016-10-12 05:00:55 -070065// PacketLossFractionSmoother uses an exponential filter with a time constant
66// of -1.0 / ln(0.9999) = 10000 ms.
67constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f;
68
kwiberg12cfc9b2015-09-08 05:57:53 -070069// Optimize the loss rate to configure Opus. Basically, optimized loss rate is
70// the input loss rate rounded down to various levels, because a robustly good
71// audio quality is achieved by lowering the packet loss down.
72// Additionally, to prevent toggling, margins are used, i.e., when jumping to
73// a loss rate from below, a higher threshold is used than jumping to the same
74// level from above.
minyue4b9a2cb2016-11-30 06:49:59 -080075float OptimizePacketLossRate(float new_loss_rate, float old_loss_rate) {
76 RTC_DCHECK_GE(new_loss_rate, 0.0f);
77 RTC_DCHECK_LE(new_loss_rate, 1.0f);
78 RTC_DCHECK_GE(old_loss_rate, 0.0f);
79 RTC_DCHECK_LE(old_loss_rate, 1.0f);
80 constexpr float kPacketLossRate20 = 0.20f;
81 constexpr float kPacketLossRate10 = 0.10f;
82 constexpr float kPacketLossRate5 = 0.05f;
83 constexpr float kPacketLossRate1 = 0.01f;
84 constexpr float kLossRate20Margin = 0.02f;
85 constexpr float kLossRate10Margin = 0.01f;
86 constexpr float kLossRate5Margin = 0.01f;
kwiberg12cfc9b2015-09-08 05:57:53 -070087 if (new_loss_rate >=
88 kPacketLossRate20 +
89 kLossRate20Margin *
90 (kPacketLossRate20 - old_loss_rate > 0 ? 1 : -1)) {
91 return kPacketLossRate20;
92 } else if (new_loss_rate >=
93 kPacketLossRate10 +
94 kLossRate10Margin *
95 (kPacketLossRate10 - old_loss_rate > 0 ? 1 : -1)) {
96 return kPacketLossRate10;
97 } else if (new_loss_rate >=
98 kPacketLossRate5 +
99 kLossRate5Margin *
100 (kPacketLossRate5 - old_loss_rate > 0 ? 1 : -1)) {
101 return kPacketLossRate5;
102 } else if (new_loss_rate >= kPacketLossRate1) {
103 return kPacketLossRate1;
104 } else {
minyue4b9a2cb2016-11-30 06:49:59 -0800105 return 0.0f;
kwiberg12cfc9b2015-09-08 05:57:53 -0700106 }
107}
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000108
ossua1a040a2017-04-06 10:03:21 -0700109int CalculateDefaultBitrate(int max_playback_rate, size_t num_channels) {
110 const int bitrate = [&] {
111 if (max_playback_rate <= 8000) {
112 return kOpusBitrateNbBps * rtc::dchecked_cast<int>(num_channels);
113 } else if (max_playback_rate <= 16000) {
114 return kOpusBitrateWbBps * rtc::dchecked_cast<int>(num_channels);
115 } else {
116 return kOpusBitrateFbBps * rtc::dchecked_cast<int>(num_channels);
117 }
118 }();
kwiberg96da0112017-06-30 04:23:22 -0700119 RTC_DCHECK_GE(bitrate, AudioEncoderOpusConfig::kMinBitrateBps);
120 RTC_DCHECK_LE(bitrate, AudioEncoderOpusConfig::kMaxBitrateBps);
ossua1a040a2017-04-06 10:03:21 -0700121 return bitrate;
122}
123
124// Get the maxaveragebitrate parameter in string-form, so we can properly figure
125// out how invalid it is and accurately log invalid values.
126int CalculateBitrate(int max_playback_rate_hz,
127 size_t num_channels,
Danil Chapovalovb6021232018-06-19 13:26:36 +0200128 absl::optional<std::string> bitrate_param) {
ossua1a040a2017-04-06 10:03:21 -0700129 const int default_bitrate =
130 CalculateDefaultBitrate(max_playback_rate_hz, num_channels);
131
132 if (bitrate_param) {
133 const auto bitrate = rtc::StringToNumber<int>(*bitrate_param);
134 if (bitrate) {
135 const int chosen_bitrate =
kwiberg96da0112017-06-30 04:23:22 -0700136 std::max(AudioEncoderOpusConfig::kMinBitrateBps,
137 std::min(*bitrate, AudioEncoderOpusConfig::kMaxBitrateBps));
ossua1a040a2017-04-06 10:03:21 -0700138 if (bitrate != chosen_bitrate) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100139 RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate " << *bitrate
140 << " clamped to " << chosen_bitrate;
ossua1a040a2017-04-06 10:03:21 -0700141 }
142 return chosen_bitrate;
143 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100144 RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate \"" << *bitrate_param
145 << "\" replaced by default bitrate " << default_bitrate;
ossua1a040a2017-04-06 10:03:21 -0700146 }
147
148 return default_bitrate;
149}
150
151int GetChannelCount(const SdpAudioFormat& format) {
152 const auto param = GetFormatParameter(format, "stereo");
153 if (param == "1") {
154 return 2;
155 } else {
156 return 1;
157 }
158}
159
160int GetMaxPlaybackRate(const SdpAudioFormat& format) {
161 const auto param = GetFormatParameter<int>(format, "maxplaybackrate");
162 if (param && *param >= 8000) {
163 return std::min(*param, kDefaultMaxPlaybackRate);
164 }
165 return kDefaultMaxPlaybackRate;
166}
167
168int GetFrameSizeMs(const SdpAudioFormat& format) {
169 const auto ptime = GetFormatParameter<int>(format, "ptime");
170 if (ptime) {
171 // Pick the next highest supported frame length from
172 // kOpusSupportedFrameLengths.
173 for (const int supported_frame_length : kOpusSupportedFrameLengths) {
174 if (supported_frame_length >= *ptime) {
175 return supported_frame_length;
176 }
177 }
178 // If none was found, return the largest supported frame length.
179 return *(std::end(kOpusSupportedFrameLengths) - 1);
180 }
181
kwiberg96da0112017-06-30 04:23:22 -0700182 return AudioEncoderOpusConfig::kDefaultFrameSizeMs;
ossua1a040a2017-04-06 10:03:21 -0700183}
184
185void FindSupportedFrameLengths(int min_frame_length_ms,
186 int max_frame_length_ms,
187 std::vector<int>* out) {
188 out->clear();
189 std::copy_if(std::begin(kANASupportedFrameLengths),
190 std::end(kANASupportedFrameLengths), std::back_inserter(*out),
191 [&](int frame_length_ms) {
192 return frame_length_ms >= min_frame_length_ms &&
193 frame_length_ms <= max_frame_length_ms;
194 });
195 RTC_DCHECK(std::is_sorted(out->begin(), out->end()));
196}
197
kwiberg96da0112017-06-30 04:23:22 -0700198int GetBitrateBps(const AudioEncoderOpusConfig& config) {
199 RTC_DCHECK(config.IsOk());
200 return *config.bitrate_bps;
201}
202
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200203bool IsValidPacketLossRate(int value) {
204 return value >= 0 && value <= 100;
205}
206
207float ToFraction(int percent) {
208 return static_cast<float>(percent) / 100;
209}
210
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200211float GetMinPacketLossRate() {
212 constexpr char kPacketLossFieldTrial[] = "WebRTC-Audio-OpusMinPacketLossRate";
213 const bool use_opus_min_packet_loss_rate =
214 webrtc::field_trial::IsEnabled(kPacketLossFieldTrial);
215 if (use_opus_min_packet_loss_rate) {
216 const std::string field_trial_string =
217 webrtc::field_trial::FindFullName(kPacketLossFieldTrial);
218 constexpr int kDefaultMinPacketLossRate = 1;
219 int value = kDefaultMinPacketLossRate;
220 if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1 &&
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200221 !IsValidPacketLossRate(value)) {
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200222 RTC_LOG(LS_WARNING) << "Invalid parameter for " << kPacketLossFieldTrial
223 << ", using default value: "
224 << kDefaultMinPacketLossRate;
225 value = kDefaultMinPacketLossRate;
226 }
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200227 return ToFraction(value);
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200228 }
229 return 0.0;
230}
231
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200232std::unique_ptr<AudioEncoderOpusImpl::NewPacketLossRateOptimizer>
233GetNewPacketLossRateOptimizer() {
234 constexpr char kPacketLossOptimizationName[] =
235 "WebRTC-Audio-NewOpusPacketLossRateOptimization";
236 const bool use_new_packet_loss_optimization =
237 webrtc::field_trial::IsEnabled(kPacketLossOptimizationName);
238 if (use_new_packet_loss_optimization) {
239 const std::string field_trial_string =
240 webrtc::field_trial::FindFullName(kPacketLossOptimizationName);
241 int min_rate;
242 int max_rate;
243 float slope;
244 if (sscanf(field_trial_string.c_str(), "Enabled-%d-%d-%f", &min_rate,
245 &max_rate, &slope) == 3 &&
246 IsValidPacketLossRate(min_rate) && IsValidPacketLossRate(max_rate)) {
247 return absl::make_unique<
248 AudioEncoderOpusImpl::NewPacketLossRateOptimizer>(
249 ToFraction(min_rate), ToFraction(max_rate), slope);
250 }
251 RTC_LOG(LS_WARNING) << "Invalid parameters for "
252 << kPacketLossOptimizationName
253 << ", using default values.";
254 return absl::make_unique<
255 AudioEncoderOpusImpl::NewPacketLossRateOptimizer>();
256 }
257 return nullptr;
258}
259
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000260} // namespace
261
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200262AudioEncoderOpusImpl::NewPacketLossRateOptimizer::NewPacketLossRateOptimizer(
263 float min_packet_loss_rate,
264 float max_packet_loss_rate,
265 float slope)
266 : min_packet_loss_rate_(min_packet_loss_rate),
267 max_packet_loss_rate_(max_packet_loss_rate),
268 slope_(slope) {}
269
270float AudioEncoderOpusImpl::NewPacketLossRateOptimizer::OptimizePacketLossRate(
271 float packet_loss_rate) const {
272 packet_loss_rate = slope_ * packet_loss_rate;
273 return std::min(std::max(packet_loss_rate, min_packet_loss_rate_),
274 max_packet_loss_rate_);
275}
276
Karl Wiberg7275e182017-10-25 09:57:40 +0200277void AudioEncoderOpusImpl::AppendSupportedEncoders(
kwiberg96da0112017-06-30 04:23:22 -0700278 std::vector<AudioCodecSpec>* specs) {
Karl Wibergeb166972019-05-16 15:14:01 +0200279 const SdpAudioFormat fmt = {"opus",
280 kRtpTimestampRateHz,
281 2,
282 {{"minptime", "10"}, {"useinbandfec", "1"}}};
kwiberg96da0112017-06-30 04:23:22 -0700283 const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
284 specs->push_back({fmt, info});
285}
286
Karl Wiberg7275e182017-10-25 09:57:40 +0200287AudioCodecInfo AudioEncoderOpusImpl::QueryAudioEncoder(
kwiberg96da0112017-06-30 04:23:22 -0700288 const AudioEncoderOpusConfig& config) {
289 RTC_DCHECK(config.IsOk());
Karl Wiberg126f2b32019-05-25 01:43:03 +0200290 AudioCodecInfo info(config.sample_rate_hz, config.num_channels,
Karl Wibergeb166972019-05-16 15:14:01 +0200291 *config.bitrate_bps,
kwiberg96da0112017-06-30 04:23:22 -0700292 AudioEncoderOpusConfig::kMinBitrateBps,
293 AudioEncoderOpusConfig::kMaxBitrateBps);
294 info.allow_comfort_noise = false;
295 info.supports_network_adaption = true;
296 return info;
297}
298
Karl Wiberg7275e182017-10-25 09:57:40 +0200299std::unique_ptr<AudioEncoder> AudioEncoderOpusImpl::MakeAudioEncoder(
kwiberg96da0112017-06-30 04:23:22 -0700300 const AudioEncoderOpusConfig& config,
301 int payload_type) {
302 RTC_DCHECK(config.IsOk());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200303 return absl::make_unique<AudioEncoderOpusImpl>(config, payload_type);
kwiberg96da0112017-06-30 04:23:22 -0700304}
305
Danil Chapovalovb6021232018-06-19 13:26:36 +0200306absl::optional<AudioEncoderOpusConfig> AudioEncoderOpusImpl::SdpToConfig(
ossua1a040a2017-04-06 10:03:21 -0700307 const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +0200308 if (!absl::EqualsIgnoreCase(format.name, "opus") ||
Karl Wibergeb166972019-05-16 15:14:01 +0200309 format.clockrate_hz != kRtpTimestampRateHz || format.num_channels != 2) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200310 return absl::nullopt;
kwiberg96da0112017-06-30 04:23:22 -0700311 }
ossua1a040a2017-04-06 10:03:21 -0700312
kwiberg96da0112017-06-30 04:23:22 -0700313 AudioEncoderOpusConfig config;
ossua1a040a2017-04-06 10:03:21 -0700314 config.num_channels = GetChannelCount(format);
315 config.frame_size_ms = GetFrameSizeMs(format);
316 config.max_playback_rate_hz = GetMaxPlaybackRate(format);
317 config.fec_enabled = (GetFormatParameter(format, "useinbandfec") == "1");
318 config.dtx_enabled = (GetFormatParameter(format, "usedtx") == "1");
ossu0d6195d2017-04-28 07:33:18 -0700319 config.cbr_enabled = (GetFormatParameter(format, "cbr") == "1");
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100320 config.bitrate_bps =
ossua1a040a2017-04-06 10:03:21 -0700321 CalculateBitrate(config.max_playback_rate_hz, config.num_channels,
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100322 GetFormatParameter(format, "maxaveragebitrate"));
kwiberg96da0112017-06-30 04:23:22 -0700323 config.application = config.num_channels == 1
324 ? AudioEncoderOpusConfig::ApplicationMode::kVoip
325 : AudioEncoderOpusConfig::ApplicationMode::kAudio;
ossua1a040a2017-04-06 10:03:21 -0700326
327 constexpr int kMinANAFrameLength = kANASupportedFrameLengths[0];
328 constexpr int kMaxANAFrameLength =
329 kANASupportedFrameLengths[arraysize(kANASupportedFrameLengths) - 1];
kwiberg96da0112017-06-30 04:23:22 -0700330
ossua1a040a2017-04-06 10:03:21 -0700331 // For now, minptime and maxptime are only used with ANA. If ptime is outside
332 // of this range, it will get adjusted once ANA takes hold. Ideally, we'd know
333 // if ANA was to be used when setting up the config, and adjust accordingly.
334 const int min_frame_length_ms =
335 GetFormatParameter<int>(format, "minptime").value_or(kMinANAFrameLength);
336 const int max_frame_length_ms =
337 GetFormatParameter<int>(format, "maxptime").value_or(kMaxANAFrameLength);
338
339 FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
340 &config.supported_frame_lengths_ms);
kwiberg96da0112017-06-30 04:23:22 -0700341 RTC_DCHECK(config.IsOk());
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100342 return config;
kwiberg96da0112017-06-30 04:23:22 -0700343}
344
Danil Chapovalovb6021232018-06-19 13:26:36 +0200345absl::optional<int> AudioEncoderOpusImpl::GetNewComplexity(
kwiberg96da0112017-06-30 04:23:22 -0700346 const AudioEncoderOpusConfig& config) {
347 RTC_DCHECK(config.IsOk());
348 const int bitrate_bps = GetBitrateBps(config);
349 if (bitrate_bps >= config.complexity_threshold_bps -
350 config.complexity_threshold_window_bps &&
351 bitrate_bps <= config.complexity_threshold_bps +
352 config.complexity_threshold_window_bps) {
353 // Within the hysteresis window; make no change.
Danil Chapovalovb6021232018-06-19 13:26:36 +0200354 return absl::nullopt;
kwiberg96da0112017-06-30 04:23:22 -0700355 } else {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100356 return bitrate_bps <= config.complexity_threshold_bps
357 ? config.low_rate_complexity
358 : config.complexity;
kwiberg96da0112017-06-30 04:23:22 -0700359 }
ossua1a040a2017-04-06 10:03:21 -0700360}
361
Danil Chapovalovb6021232018-06-19 13:26:36 +0200362absl::optional<int> AudioEncoderOpusImpl::GetNewBandwidth(
Alex Luebseeb27652017-11-20 11:13:56 -0800363 const AudioEncoderOpusConfig& config,
364 OpusEncInst* inst) {
365 constexpr int kMinWidebandBitrate = 8000;
366 constexpr int kMaxNarrowbandBitrate = 9000;
367 constexpr int kAutomaticThreshold = 11000;
368 RTC_DCHECK(config.IsOk());
369 const int bitrate = GetBitrateBps(config);
370 if (bitrate > kAutomaticThreshold) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200371 return absl::optional<int>(OPUS_AUTO);
Alex Luebseeb27652017-11-20 11:13:56 -0800372 }
373 const int bandwidth = WebRtcOpus_GetBandwidth(inst);
374 RTC_DCHECK_GE(bandwidth, 0);
375 if (bitrate > kMaxNarrowbandBitrate && bandwidth < OPUS_BANDWIDTH_WIDEBAND) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200376 return absl::optional<int>(OPUS_BANDWIDTH_WIDEBAND);
Alex Luebseeb27652017-11-20 11:13:56 -0800377 } else if (bitrate < kMinWidebandBitrate &&
378 bandwidth > OPUS_BANDWIDTH_NARROWBAND) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200379 return absl::optional<int>(OPUS_BANDWIDTH_NARROWBAND);
Alex Luebseeb27652017-11-20 11:13:56 -0800380 }
Danil Chapovalovb6021232018-06-19 13:26:36 +0200381 return absl::optional<int>();
Alex Luebseeb27652017-11-20 11:13:56 -0800382}
383
Karl Wiberg7275e182017-10-25 09:57:40 +0200384class AudioEncoderOpusImpl::PacketLossFractionSmoother {
minyue7e304322016-10-12 05:00:55 -0700385 public:
michaelt92aef172017-04-18 00:11:48 -0700386 explicit PacketLossFractionSmoother()
387 : last_sample_time_ms_(rtc::TimeMillis()),
minyue7e304322016-10-12 05:00:55 -0700388 smoother_(kAlphaForPacketLossFractionSmoother) {}
389
390 // Gets the smoothed packet loss fraction.
391 float GetAverage() const {
392 float value = smoother_.filtered();
393 return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value;
394 }
395
396 // Add new observation to the packet loss fraction smoother.
397 void AddSample(float packet_loss_fraction) {
michaelt92aef172017-04-18 00:11:48 -0700398 int64_t now_ms = rtc::TimeMillis();
minyue7e304322016-10-12 05:00:55 -0700399 smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_),
400 packet_loss_fraction);
401 last_sample_time_ms_ = now_ms;
402 }
403
404 private:
minyue7e304322016-10-12 05:00:55 -0700405 int64_t last_sample_time_ms_;
406
407 // An exponential filter is used to smooth the packet loss fraction.
408 rtc::ExpFilter smoother_;
409};
410
Karl Wiberg7275e182017-10-25 09:57:40 +0200411AudioEncoderOpusImpl::AudioEncoderOpusImpl(const AudioEncoderOpusConfig& config,
412 int payload_type)
413 : AudioEncoderOpusImpl(
minyue-webrtc5d689102017-08-14 14:33:32 +0200414 config,
415 payload_type,
Mirko Bonadeie45c6882019-02-16 09:59:29 +0100416 [this](const std::string& config_string, RtcEventLog* event_log) {
minyue-webrtc5d689102017-08-14 14:33:32 +0200417 return DefaultAudioNetworkAdaptorCreator(config_string, event_log);
418 },
419 // We choose 5sec as initial time constant due to empirical data.
Karl Wiberg918f50c2018-07-05 11:40:33 +0200420 absl::make_unique<SmoothingFilterImpl>(5000)) {}
minyue-webrtc5d689102017-08-14 14:33:32 +0200421
Karl Wiberg7275e182017-10-25 09:57:40 +0200422AudioEncoderOpusImpl::AudioEncoderOpusImpl(
kwiberg96da0112017-06-30 04:23:22 -0700423 const AudioEncoderOpusConfig& config,
424 int payload_type,
minyue-webrtc5d689102017-08-14 14:33:32 +0200425 const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
michaelt566d8202017-01-12 10:17:38 -0800426 std::unique_ptr<SmoothingFilter> bitrate_smoother)
kwiberg96da0112017-06-30 04:23:22 -0700427 : payload_type_(payload_type),
minyue-webrtc5d689102017-08-14 14:33:32 +0200428 send_side_bwe_with_overhead_(
429 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100430 use_link_capacity_for_adaptation_(webrtc::field_trial::IsEnabled(
431 "WebRTC-Audio-LinkCapacityAdaptation")),
Alex Luebseeb27652017-11-20 11:13:56 -0800432 adjust_bandwidth_(
433 webrtc::field_trial::IsEnabled("WebRTC-AdjustOpusBandwidth")),
434 bitrate_changed_(true),
elad.alon0fe12162017-01-31 05:48:37 -0800435 packet_loss_rate_(0.0),
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200436 min_packet_loss_rate_(GetMinPacketLossRate()),
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200437 new_packet_loss_optimizer_(GetNewPacketLossRateOptimizer()),
minyue41b9c802016-10-06 07:13:54 -0700438 inst_(nullptr),
michaelt92aef172017-04-18 00:11:48 -0700439 packet_loss_fraction_smoother_(new PacketLossFractionSmoother()),
minyue-webrtc5d689102017-08-14 14:33:32 +0200440 audio_network_adaptor_creator_(audio_network_adaptor_creator),
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100441 bitrate_smoother_(std::move(bitrate_smoother)),
442 consecutive_dtx_frames_(0) {
minyue-webrtc5d689102017-08-14 14:33:32 +0200443 RTC_DCHECK(0 <= payload_type && payload_type <= 127);
kwiberg96da0112017-06-30 04:23:22 -0700444
445 // Sanity check of the redundant payload type field that we want to get rid
446 // of. See https://bugs.chromium.org/p/webrtc/issues/detail?id=7847
447 RTC_CHECK(config.payload_type == -1 || config.payload_type == payload_type);
448
henrikg91d6ede2015-09-17 00:24:34 -0700449 RTC_CHECK(RecreateEncoderInstance(config));
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200450 SetProjectedPacketLossRate(packet_loss_rate_);
kwiberg12cfc9b2015-09-08 05:57:53 -0700451}
452
Karl Wiberg7275e182017-10-25 09:57:40 +0200453AudioEncoderOpusImpl::AudioEncoderOpusImpl(int payload_type,
454 const SdpAudioFormat& format)
455 : AudioEncoderOpusImpl(*SdpToConfig(format), payload_type) {}
ossua1a040a2017-04-06 10:03:21 -0700456
Karl Wiberg7275e182017-10-25 09:57:40 +0200457AudioEncoderOpusImpl::~AudioEncoderOpusImpl() {
henrikg91d6ede2015-09-17 00:24:34 -0700458 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700459}
460
Karl Wiberg7275e182017-10-25 09:57:40 +0200461int AudioEncoderOpusImpl::SampleRateHz() const {
Karl Wiberg126f2b32019-05-25 01:43:03 +0200462 return config_.sample_rate_hz;
kwiberg12cfc9b2015-09-08 05:57:53 -0700463}
464
Karl Wiberg7275e182017-10-25 09:57:40 +0200465size_t AudioEncoderOpusImpl::NumChannels() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700466 return config_.num_channels;
467}
468
Karl Wibergeb166972019-05-16 15:14:01 +0200469int AudioEncoderOpusImpl::RtpTimestampRateHz() const {
470 return kRtpTimestampRateHz;
471}
472
Karl Wiberg7275e182017-10-25 09:57:40 +0200473size_t AudioEncoderOpusImpl::Num10MsFramesInNextPacket() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700474 return Num10msFramesPerPacket();
475}
476
Karl Wiberg7275e182017-10-25 09:57:40 +0200477size_t AudioEncoderOpusImpl::Max10MsFramesInAPacket() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700478 return Num10msFramesPerPacket();
479}
480
Karl Wiberg7275e182017-10-25 09:57:40 +0200481int AudioEncoderOpusImpl::GetTargetBitrate() const {
kwiberg96da0112017-06-30 04:23:22 -0700482 return GetBitrateBps(config_);
kwiberg12cfc9b2015-09-08 05:57:53 -0700483}
484
Karl Wiberg7275e182017-10-25 09:57:40 +0200485void AudioEncoderOpusImpl::Reset() {
henrikg91d6ede2015-09-17 00:24:34 -0700486 RTC_CHECK(RecreateEncoderInstance(config_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700487}
488
Karl Wiberg7275e182017-10-25 09:57:40 +0200489bool AudioEncoderOpusImpl::SetFec(bool enable) {
minyue41b9c802016-10-06 07:13:54 -0700490 if (enable) {
491 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
492 } else {
493 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
494 }
495 config_.fec_enabled = enable;
496 return true;
kwiberg12cfc9b2015-09-08 05:57:53 -0700497}
498
Karl Wiberg7275e182017-10-25 09:57:40 +0200499bool AudioEncoderOpusImpl::SetDtx(bool enable) {
minyue41b9c802016-10-06 07:13:54 -0700500 if (enable) {
501 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
502 } else {
503 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
504 }
505 config_.dtx_enabled = enable;
506 return true;
kwiberg12cfc9b2015-09-08 05:57:53 -0700507}
508
Karl Wiberg7275e182017-10-25 09:57:40 +0200509bool AudioEncoderOpusImpl::GetDtx() const {
ivoc85228d62016-07-27 04:53:47 -0700510 return config_.dtx_enabled;
511}
512
Karl Wiberg7275e182017-10-25 09:57:40 +0200513bool AudioEncoderOpusImpl::SetApplication(Application application) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700514 auto conf = config_;
515 switch (application) {
516 case Application::kSpeech:
kwiberg96da0112017-06-30 04:23:22 -0700517 conf.application = AudioEncoderOpusConfig::ApplicationMode::kVoip;
kwiberg12cfc9b2015-09-08 05:57:53 -0700518 break;
519 case Application::kAudio:
kwiberg96da0112017-06-30 04:23:22 -0700520 conf.application = AudioEncoderOpusConfig::ApplicationMode::kAudio;
kwiberg12cfc9b2015-09-08 05:57:53 -0700521 break;
522 }
523 return RecreateEncoderInstance(conf);
524}
525
Karl Wiberg7275e182017-10-25 09:57:40 +0200526void AudioEncoderOpusImpl::SetMaxPlaybackRate(int frequency_hz) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700527 auto conf = config_;
528 conf.max_playback_rate_hz = frequency_hz;
henrikg91d6ede2015-09-17 00:24:34 -0700529 RTC_CHECK(RecreateEncoderInstance(conf));
kwiberg12cfc9b2015-09-08 05:57:53 -0700530}
531
Karl Wiberg7275e182017-10-25 09:57:40 +0200532bool AudioEncoderOpusImpl::EnableAudioNetworkAdaptor(
minyue41b9c802016-10-06 07:13:54 -0700533 const std::string& config_string,
michaelt92aef172017-04-18 00:11:48 -0700534 RtcEventLog* event_log) {
michaeltbf279fc2017-01-13 06:02:29 -0800535 audio_network_adaptor_ =
michaelt92aef172017-04-18 00:11:48 -0700536 audio_network_adaptor_creator_(config_string, event_log);
minyue41b9c802016-10-06 07:13:54 -0700537 return audio_network_adaptor_.get() != nullptr;
538}
539
Karl Wiberg7275e182017-10-25 09:57:40 +0200540void AudioEncoderOpusImpl::DisableAudioNetworkAdaptor() {
minyue41b9c802016-10-06 07:13:54 -0700541 audio_network_adaptor_.reset(nullptr);
542}
543
Karl Wiberg7275e182017-10-25 09:57:40 +0200544void AudioEncoderOpusImpl::OnReceivedUplinkPacketLossFraction(
minyue41b9c802016-10-06 07:13:54 -0700545 float uplink_packet_loss_fraction) {
minyue7e304322016-10-12 05:00:55 -0700546 if (!audio_network_adaptor_) {
547 packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction);
548 float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage();
549 return SetProjectedPacketLossRate(average_fraction_loss);
550 }
minyue41b9c802016-10-06 07:13:54 -0700551 audio_network_adaptor_->SetUplinkPacketLossFraction(
552 uplink_packet_loss_fraction);
553 ApplyAudioNetworkAdaptor();
554}
555
Karl Wiberg7275e182017-10-25 09:57:40 +0200556void AudioEncoderOpusImpl::OnReceivedUplinkRecoverablePacketLossFraction(
elad.alondadb4dc2017-03-23 15:29:50 -0700557 float uplink_recoverable_packet_loss_fraction) {
558 if (!audio_network_adaptor_)
559 return;
560 audio_network_adaptor_->SetUplinkRecoverablePacketLossFraction(
561 uplink_recoverable_packet_loss_fraction);
562 ApplyAudioNetworkAdaptor();
563}
564
Karl Wiberg7275e182017-10-25 09:57:40 +0200565void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
michaelt566d8202017-01-12 10:17:38 -0800566 int target_audio_bitrate_bps,
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100567 absl::optional<int64_t> bwe_period_ms,
568 absl::optional<int64_t> link_capacity_allocation_bps) {
minyueeca373f2016-12-07 01:40:34 -0800569 if (audio_network_adaptor_) {
570 audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
michaelt566d8202017-01-12 10:17:38 -0800571 // We give smoothed bitrate allocation to audio network adaptor as
572 // the uplink bandwidth.
minyue-webrtcbf94fda2017-09-01 10:44:37 +0200573 // The BWE spikes should not affect the bitrate smoother more than 25%.
michaelt566d8202017-01-12 10:17:38 -0800574 // To simplify the calculations we use a step response as input signal.
575 // The step response of an exponential filter is
576 // u(t) = 1 - e^(-t / time_constant).
577 // In order to limit the affect of a BWE spike within 25% of its value
578 // before
minyue-webrtcbf94fda2017-09-01 10:44:37 +0200579 // the next BWE update, we would choose a time constant that fulfills
580 // 1 - e^(-bwe_period_ms / time_constant) < 0.25
581 // Then 4 * bwe_period_ms is a good choice.
582 if (bwe_period_ms)
583 bitrate_smoother_->SetTimeConstantMs(*bwe_period_ms * 4);
michaelt566d8202017-01-12 10:17:38 -0800584 bitrate_smoother_->AddSample(target_audio_bitrate_bps);
585
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100586 if (link_capacity_allocation_bps)
587 link_capacity_allocation_bps_ = link_capacity_allocation_bps;
588
minyueeca373f2016-12-07 01:40:34 -0800589 ApplyAudioNetworkAdaptor();
elad.alon0fe12162017-01-31 05:48:37 -0800590 } else if (send_side_bwe_with_overhead_) {
minyueeca373f2016-12-07 01:40:34 -0800591 if (!overhead_bytes_per_packet_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100592 RTC_LOG(LS_INFO)
Karl Wiberg7275e182017-10-25 09:57:40 +0200593 << "AudioEncoderOpusImpl: Overhead unknown, target audio bitrate "
minyueeca373f2016-12-07 01:40:34 -0800594 << target_audio_bitrate_bps << " bps is ignored.";
595 return;
596 }
597 const int overhead_bps = static_cast<int>(
598 *overhead_bytes_per_packet_ * 8 * 100 / Num10MsFramesInNextPacket());
kwiberg96da0112017-06-30 04:23:22 -0700599 SetTargetBitrate(
600 std::min(AudioEncoderOpusConfig::kMaxBitrateBps,
601 std::max(AudioEncoderOpusConfig::kMinBitrateBps,
602 target_audio_bitrate_bps - overhead_bps)));
minyueeca373f2016-12-07 01:40:34 -0800603 } else {
604 SetTargetBitrate(target_audio_bitrate_bps);
605 }
minyue41b9c802016-10-06 07:13:54 -0700606}
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100607void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
608 int target_audio_bitrate_bps,
609 absl::optional<int64_t> bwe_period_ms) {
610 OnReceivedUplinkBandwidth(target_audio_bitrate_bps, bwe_period_ms,
611 absl::nullopt);
612}
613
614void AudioEncoderOpusImpl::OnReceivedUplinkAllocation(
615 BitrateAllocationUpdate update) {
616 OnReceivedUplinkBandwidth(update.target_bitrate.bps(), update.bwe_period.ms(),
617 update.link_capacity.bps());
618}
minyue41b9c802016-10-06 07:13:54 -0700619
Karl Wiberg7275e182017-10-25 09:57:40 +0200620void AudioEncoderOpusImpl::OnReceivedRtt(int rtt_ms) {
minyue41b9c802016-10-06 07:13:54 -0700621 if (!audio_network_adaptor_)
622 return;
623 audio_network_adaptor_->SetRtt(rtt_ms);
624 ApplyAudioNetworkAdaptor();
625}
626
Karl Wiberg7275e182017-10-25 09:57:40 +0200627void AudioEncoderOpusImpl::OnReceivedOverhead(
628 size_t overhead_bytes_per_packet) {
minyueeca373f2016-12-07 01:40:34 -0800629 if (audio_network_adaptor_) {
630 audio_network_adaptor_->SetOverhead(overhead_bytes_per_packet);
631 ApplyAudioNetworkAdaptor();
632 } else {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100633 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
minyueeca373f2016-12-07 01:40:34 -0800634 }
635}
636
Karl Wiberg7275e182017-10-25 09:57:40 +0200637void AudioEncoderOpusImpl::SetReceiverFrameLengthRange(
638 int min_frame_length_ms,
639 int max_frame_length_ms) {
minyuea6f495c2016-10-24 09:19:14 -0700640 // Ensure that |SetReceiverFrameLengthRange| is called before
641 // |EnableAudioNetworkAdaptor|, otherwise we need to recreate
642 // |audio_network_adaptor_|, which is not a needed use case.
643 RTC_DCHECK(!audio_network_adaptor_);
ossua1a040a2017-04-06 10:03:21 -0700644 FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
645 &config_.supported_frame_lengths_ms);
minyue41b9c802016-10-06 07:13:54 -0700646}
647
Karl Wiberg7275e182017-10-25 09:57:40 +0200648AudioEncoder::EncodedInfo AudioEncoderOpusImpl::EncodeImpl(
ossu10a029e2016-03-01 00:41:31 -0800649 uint32_t rtp_timestamp,
650 rtc::ArrayView<const int16_t> audio,
651 rtc::Buffer* encoded) {
michaelt566d8202017-01-12 10:17:38 -0800652 MaybeUpdateUplinkBandwidth();
ossu10a029e2016-03-01 00:41:31 -0800653
654 if (input_buffer_.empty())
655 first_timestamp_in_buffer_ = rtp_timestamp;
656
657 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
658 if (input_buffer_.size() <
659 (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
660 return EncodedInfo();
661 }
662 RTC_CHECK_EQ(input_buffer_.size(),
663 Num10msFramesPerPacket() * SamplesPer10msFrame());
664
ossu2903ba52016-04-18 06:14:33 -0700665 const size_t max_encoded_bytes = SufficientOutputBufferSize();
ossu10a029e2016-03-01 00:41:31 -0800666 EncodedInfo info;
Yves Gerey665174f2018-06-19 15:03:05 +0200667 info.encoded_bytes = encoded->AppendData(
668 max_encoded_bytes, [&](rtc::ArrayView<uint8_t> encoded) {
669 int status = WebRtcOpus_Encode(
670 inst_, &input_buffer_[0],
671 rtc::CheckedDivExact(input_buffer_.size(), config_.num_channels),
672 rtc::saturated_cast<int16_t>(max_encoded_bytes), encoded.data());
ossu10a029e2016-03-01 00:41:31 -0800673
Yves Gerey665174f2018-06-19 15:03:05 +0200674 RTC_CHECK_GE(status, 0); // Fails only if fed invalid data.
ossu10a029e2016-03-01 00:41:31 -0800675
Yves Gerey665174f2018-06-19 15:03:05 +0200676 return static_cast<size_t>(status);
677 });
ossu10a029e2016-03-01 00:41:31 -0800678 input_buffer_.clear();
679
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100680 bool dtx_frame = (info.encoded_bytes <= 2);
681
minyue41b9c802016-10-06 07:13:54 -0700682 // Will use new packet size for next encoding.
683 config_.frame_size_ms = next_frame_length_ms_;
684
Alex Luebseeb27652017-11-20 11:13:56 -0800685 if (adjust_bandwidth_ && bitrate_changed_) {
686 const auto bandwidth = GetNewBandwidth(config_, inst_);
687 if (bandwidth) {
688 RTC_CHECK_EQ(0, WebRtcOpus_SetBandwidth(inst_, *bandwidth));
689 }
690 bitrate_changed_ = false;
691 }
692
ossu10a029e2016-03-01 00:41:31 -0800693 info.encoded_timestamp = first_timestamp_in_buffer_;
kwiberg96da0112017-06-30 04:23:22 -0700694 info.payload_type = payload_type_;
ossu10a029e2016-03-01 00:41:31 -0800695 info.send_even_if_empty = true; // Allows Opus to send empty packets.
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100696 // After 20 DTX frames (MAX_CONSECUTIVE_DTX) Opus will send a frame
697 // coding the background noise. Avoid flagging this frame as speech
698 // (even though there is a probability of the frame being speech).
699 info.speech = !dtx_frame && (consecutive_dtx_frames_ != 20);
aleloi8bce67b2016-05-16 07:34:24 -0700700 info.encoder_type = CodecType::kOpus;
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100701
702 // Increase or reset DTX counter.
703 consecutive_dtx_frames_ = (dtx_frame) ? (consecutive_dtx_frames_ + 1) : (0);
704
ossu10a029e2016-03-01 00:41:31 -0800705 return info;
706}
707
Karl Wiberg7275e182017-10-25 09:57:40 +0200708size_t AudioEncoderOpusImpl::Num10msFramesPerPacket() const {
pkasting25702cb2016-01-08 13:50:27 -0800709 return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
kwiberg12cfc9b2015-09-08 05:57:53 -0700710}
711
Karl Wiberg7275e182017-10-25 09:57:40 +0200712size_t AudioEncoderOpusImpl::SamplesPer10msFrame() const {
Karl Wiberg126f2b32019-05-25 01:43:03 +0200713 return rtc::CheckedDivExact(config_.sample_rate_hz, 100) *
714 config_.num_channels;
kwiberg12cfc9b2015-09-08 05:57:53 -0700715}
716
Karl Wiberg7275e182017-10-25 09:57:40 +0200717size_t AudioEncoderOpusImpl::SufficientOutputBufferSize() const {
ossu2903ba52016-04-18 06:14:33 -0700718 // Calculate the number of bytes we expect the encoder to produce,
719 // then multiply by two to give a wide margin for error.
720 const size_t bytes_per_millisecond =
kwiberg96da0112017-06-30 04:23:22 -0700721 static_cast<size_t>(GetBitrateBps(config_) / (1000 * 8) + 1);
ossu2903ba52016-04-18 06:14:33 -0700722 const size_t approx_encoded_bytes =
723 Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
724 return 2 * approx_encoded_bytes;
725}
726
kwiberg12cfc9b2015-09-08 05:57:53 -0700727// If the given config is OK, recreate the Opus encoder instance with those
728// settings, save the config, and return true. Otherwise, do nothing and return
729// false.
Karl Wiberg7275e182017-10-25 09:57:40 +0200730bool AudioEncoderOpusImpl::RecreateEncoderInstance(
kwiberg96da0112017-06-30 04:23:22 -0700731 const AudioEncoderOpusConfig& config) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700732 if (!config.IsOk())
733 return false;
elad.aloncfd88bb2017-03-14 02:50:46 -0700734 config_ = config;
kwiberg12cfc9b2015-09-08 05:57:53 -0700735 if (inst_)
henrikg91d6ede2015-09-17 00:24:34 -0700736 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700737 input_buffer_.clear();
738 input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
kwiberg96da0112017-06-30 04:23:22 -0700739 RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(
740 &inst_, config.num_channels,
741 config.application ==
742 AudioEncoderOpusConfig::ApplicationMode::kVoip
743 ? 0
Karl Wiberg7e7c5c32019-05-21 11:50:32 +0200744 : 1,
Karl Wiberg126f2b32019-05-25 01:43:03 +0200745 config.sample_rate_hz));
Minyue Li9dac02d2019-01-18 11:09:47 +0100746 const int bitrate = GetBitrateBps(config);
747 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
748 RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000749 if (config.fec_enabled) {
henrikg91d6ede2015-09-17 00:24:34 -0700750 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000751 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700752 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000753 }
henrikg91d6ede2015-09-17 00:24:34 -0700754 RTC_CHECK_EQ(
755 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
henrik.lundin875862c2016-11-22 02:07:54 -0800756 // Use the default complexity if the start bitrate is within the hysteresis
757 // window.
kwiberg96da0112017-06-30 04:23:22 -0700758 complexity_ = GetNewComplexity(config).value_or(config.complexity);
henrik.lundin875862c2016-11-22 02:07:54 -0800759 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
Alex Luebseeb27652017-11-20 11:13:56 -0800760 bitrate_changed_ = true;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000761 if (config.dtx_enabled) {
henrikg91d6ede2015-09-17 00:24:34 -0700762 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000763 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700764 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000765 }
henrikg91d6ede2015-09-17 00:24:34 -0700766 RTC_CHECK_EQ(0,
767 WebRtcOpus_SetPacketLossRate(
768 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
ossu0d6195d2017-04-28 07:33:18 -0700769 if (config.cbr_enabled) {
770 RTC_CHECK_EQ(0, WebRtcOpus_EnableCbr(inst_));
771 } else {
772 RTC_CHECK_EQ(0, WebRtcOpus_DisableCbr(inst_));
773 }
minyue41b9c802016-10-06 07:13:54 -0700774 num_channels_to_encode_ = NumChannels();
775 next_frame_length_ms_ = config_.frame_size_ms;
kwiberg12cfc9b2015-09-08 05:57:53 -0700776 return true;
Karl Wibergdcccab32015-05-07 12:35:12 +0200777}
778
Karl Wiberg7275e182017-10-25 09:57:40 +0200779void AudioEncoderOpusImpl::SetFrameLength(int frame_length_ms) {
minyue41b9c802016-10-06 07:13:54 -0700780 next_frame_length_ms_ = frame_length_ms;
781}
782
Karl Wiberg7275e182017-10-25 09:57:40 +0200783void AudioEncoderOpusImpl::SetNumChannelsToEncode(
784 size_t num_channels_to_encode) {
kwibergaf476c72016-11-28 15:21:39 -0800785 RTC_DCHECK_GT(num_channels_to_encode, 0);
minyue41b9c802016-10-06 07:13:54 -0700786 RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels);
787
788 if (num_channels_to_encode_ == num_channels_to_encode)
789 return;
790
791 RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode));
792 num_channels_to_encode_ = num_channels_to_encode;
793}
794
Karl Wiberg7275e182017-10-25 09:57:40 +0200795void AudioEncoderOpusImpl::SetProjectedPacketLossRate(float fraction) {
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200796 if (new_packet_loss_optimizer_) {
797 fraction = new_packet_loss_optimizer_->OptimizePacketLossRate(fraction);
798 } else {
799 fraction = OptimizePacketLossRate(fraction, packet_loss_rate_);
800 fraction = std::max(fraction, min_packet_loss_rate_);
801 }
802 if (packet_loss_rate_ != fraction) {
803 packet_loss_rate_ = fraction;
minyue4b9a2cb2016-11-30 06:49:59 -0800804 RTC_CHECK_EQ(
805 0, WebRtcOpus_SetPacketLossRate(
806 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
807 }
808}
809
Karl Wiberg7275e182017-10-25 09:57:40 +0200810void AudioEncoderOpusImpl::SetTargetBitrate(int bits_per_second) {
Minyue Li9dac02d2019-01-18 11:09:47 +0100811 const int new_bitrate = rtc::SafeClamp<int>(
kwiberg96da0112017-06-30 04:23:22 -0700812 bits_per_second, AudioEncoderOpusConfig::kMinBitrateBps,
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100813 AudioEncoderOpusConfig::kMaxBitrateBps);
Minyue Li9dac02d2019-01-18 11:09:47 +0100814 if (config_.bitrate_bps && *config_.bitrate_bps != new_bitrate) {
815 config_.bitrate_bps = new_bitrate;
816 RTC_DCHECK(config_.IsOk());
817 const int bitrate = GetBitrateBps(config_);
818 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
819 RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
820 bitrate_changed_ = true;
821 }
822
kwiberg96da0112017-06-30 04:23:22 -0700823 const auto new_complexity = GetNewComplexity(config_);
minyue4b9a2cb2016-11-30 06:49:59 -0800824 if (new_complexity && complexity_ != *new_complexity) {
825 complexity_ = *new_complexity;
826 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
827 }
828}
829
Karl Wiberg7275e182017-10-25 09:57:40 +0200830void AudioEncoderOpusImpl::ApplyAudioNetworkAdaptor() {
minyue41b9c802016-10-06 07:13:54 -0700831 auto config = audio_network_adaptor_->GetEncoderRuntimeConfig();
minyue41b9c802016-10-06 07:13:54 -0700832
michaelt584c35a2016-12-27 08:21:29 -0800833 if (config.bitrate_bps)
834 SetTargetBitrate(*config.bitrate_bps);
835 if (config.frame_length_ms)
836 SetFrameLength(*config.frame_length_ms);
837 if (config.enable_fec)
838 SetFec(*config.enable_fec);
839 if (config.uplink_packet_loss_fraction)
840 SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction);
841 if (config.enable_dtx)
842 SetDtx(*config.enable_dtx);
843 if (config.num_channels)
844 SetNumChannelsToEncode(*config.num_channels);
minyue41b9c802016-10-06 07:13:54 -0700845}
846
847std::unique_ptr<AudioNetworkAdaptor>
Karl Wiberg7275e182017-10-25 09:57:40 +0200848AudioEncoderOpusImpl::DefaultAudioNetworkAdaptorCreator(
Mirko Bonadeie45c6882019-02-16 09:59:29 +0100849 const std::string& config_string,
michaelt92aef172017-04-18 00:11:48 -0700850 RtcEventLog* event_log) const {
minyue41b9c802016-10-06 07:13:54 -0700851 AudioNetworkAdaptorImpl::Config config;
michaeltbf279fc2017-01-13 06:02:29 -0800852 config.event_log = event_log;
minyue41b9c802016-10-06 07:13:54 -0700853 return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl(
kwiberg96da0112017-06-30 04:23:22 -0700854 config, ControllerManagerImpl::Create(
855 config_string, NumChannels(), supported_frame_lengths_ms(),
856 AudioEncoderOpusConfig::kMinBitrateBps,
857 num_channels_to_encode_, next_frame_length_ms_,
858 GetTargetBitrate(), config_.fec_enabled, GetDtx())));
minyue41b9c802016-10-06 07:13:54 -0700859}
860
Karl Wiberg7275e182017-10-25 09:57:40 +0200861void AudioEncoderOpusImpl::MaybeUpdateUplinkBandwidth() {
michaelt566d8202017-01-12 10:17:38 -0800862 if (audio_network_adaptor_) {
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100863 if (use_link_capacity_for_adaptation_ && link_capacity_allocation_bps_) {
864 audio_network_adaptor_->SetUplinkBandwidth(
865 *link_capacity_allocation_bps_);
866 } else {
867 int64_t now_ms = rtc::TimeMillis();
868 if (!bitrate_smoother_last_update_time_ ||
869 now_ms - *bitrate_smoother_last_update_time_ >=
870 config_.uplink_bandwidth_update_interval_ms) {
871 absl::optional<float> smoothed_bitrate =
872 bitrate_smoother_->GetAverage();
873 if (smoothed_bitrate)
874 audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
875 bitrate_smoother_last_update_time_ = now_ms;
876 }
michaelt566d8202017-01-12 10:17:38 -0800877 }
878 }
879}
880
Karl Wiberg7275e182017-10-25 09:57:40 +0200881ANAStats AudioEncoderOpusImpl::GetANAStats() const {
ivoce1198e02017-09-08 08:13:19 -0700882 if (audio_network_adaptor_) {
883 return audio_network_adaptor_->GetStats();
884 }
885 return ANAStats();
886}
887
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000888} // namespace webrtc