blob: 18b9ac585e9e345f7c8e47690975935df05323fb [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
ossua1a040a2017-04-06 10:03:21 -070053constexpr int kSampleRateHz = 48000;
Karl Wibergeb166972019-05-16 15:14:01 +020054constexpr int kRtpTimestampRateHz = 48000;
ossua1a040a2017-04-06 10:03:21 -070055constexpr int kDefaultMaxPlaybackRate = 48000;
michaelta55f0212017-02-02 07:47:19 -080056
ossua1a040a2017-04-06 10:03:21 -070057// These two lists must be sorted from low to high
michaelta55f0212017-02-02 07:47:19 -080058#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
ossua1a040a2017-04-06 10:03:21 -070059constexpr int kANASupportedFrameLengths[] = {20, 60, 120};
60constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60, 120};
michaelta55f0212017-02-02 07:47:19 -080061#else
ossua1a040a2017-04-06 10:03:21 -070062constexpr int kANASupportedFrameLengths[] = {20, 60};
63constexpr int kOpusSupportedFrameLengths[] = {10, 20, 40, 60};
michaelta55f0212017-02-02 07:47:19 -080064#endif
henrik.lundin@webrtc.org478cedc2015-01-27 18:24:45 +000065
minyue7e304322016-10-12 05:00:55 -070066// PacketLossFractionSmoother uses an exponential filter with a time constant
67// of -1.0 / ln(0.9999) = 10000 ms.
68constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f;
69
kwiberg12cfc9b2015-09-08 05:57:53 -070070// Optimize the loss rate to configure Opus. Basically, optimized loss rate is
71// the input loss rate rounded down to various levels, because a robustly good
72// audio quality is achieved by lowering the packet loss down.
73// Additionally, to prevent toggling, margins are used, i.e., when jumping to
74// a loss rate from below, a higher threshold is used than jumping to the same
75// level from above.
minyue4b9a2cb2016-11-30 06:49:59 -080076float OptimizePacketLossRate(float new_loss_rate, float old_loss_rate) {
77 RTC_DCHECK_GE(new_loss_rate, 0.0f);
78 RTC_DCHECK_LE(new_loss_rate, 1.0f);
79 RTC_DCHECK_GE(old_loss_rate, 0.0f);
80 RTC_DCHECK_LE(old_loss_rate, 1.0f);
81 constexpr float kPacketLossRate20 = 0.20f;
82 constexpr float kPacketLossRate10 = 0.10f;
83 constexpr float kPacketLossRate5 = 0.05f;
84 constexpr float kPacketLossRate1 = 0.01f;
85 constexpr float kLossRate20Margin = 0.02f;
86 constexpr float kLossRate10Margin = 0.01f;
87 constexpr float kLossRate5Margin = 0.01f;
kwiberg12cfc9b2015-09-08 05:57:53 -070088 if (new_loss_rate >=
89 kPacketLossRate20 +
90 kLossRate20Margin *
91 (kPacketLossRate20 - old_loss_rate > 0 ? 1 : -1)) {
92 return kPacketLossRate20;
93 } else if (new_loss_rate >=
94 kPacketLossRate10 +
95 kLossRate10Margin *
96 (kPacketLossRate10 - old_loss_rate > 0 ? 1 : -1)) {
97 return kPacketLossRate10;
98 } else if (new_loss_rate >=
99 kPacketLossRate5 +
100 kLossRate5Margin *
101 (kPacketLossRate5 - old_loss_rate > 0 ? 1 : -1)) {
102 return kPacketLossRate5;
103 } else if (new_loss_rate >= kPacketLossRate1) {
104 return kPacketLossRate1;
105 } else {
minyue4b9a2cb2016-11-30 06:49:59 -0800106 return 0.0f;
kwiberg12cfc9b2015-09-08 05:57:53 -0700107 }
108}
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000109
ossua1a040a2017-04-06 10:03:21 -0700110int CalculateDefaultBitrate(int max_playback_rate, size_t num_channels) {
111 const int bitrate = [&] {
112 if (max_playback_rate <= 8000) {
113 return kOpusBitrateNbBps * rtc::dchecked_cast<int>(num_channels);
114 } else if (max_playback_rate <= 16000) {
115 return kOpusBitrateWbBps * rtc::dchecked_cast<int>(num_channels);
116 } else {
117 return kOpusBitrateFbBps * rtc::dchecked_cast<int>(num_channels);
118 }
119 }();
kwiberg96da0112017-06-30 04:23:22 -0700120 RTC_DCHECK_GE(bitrate, AudioEncoderOpusConfig::kMinBitrateBps);
121 RTC_DCHECK_LE(bitrate, AudioEncoderOpusConfig::kMaxBitrateBps);
ossua1a040a2017-04-06 10:03:21 -0700122 return bitrate;
123}
124
125// Get the maxaveragebitrate parameter in string-form, so we can properly figure
126// out how invalid it is and accurately log invalid values.
127int CalculateBitrate(int max_playback_rate_hz,
128 size_t num_channels,
Danil Chapovalovb6021232018-06-19 13:26:36 +0200129 absl::optional<std::string> bitrate_param) {
ossua1a040a2017-04-06 10:03:21 -0700130 const int default_bitrate =
131 CalculateDefaultBitrate(max_playback_rate_hz, num_channels);
132
133 if (bitrate_param) {
134 const auto bitrate = rtc::StringToNumber<int>(*bitrate_param);
135 if (bitrate) {
136 const int chosen_bitrate =
kwiberg96da0112017-06-30 04:23:22 -0700137 std::max(AudioEncoderOpusConfig::kMinBitrateBps,
138 std::min(*bitrate, AudioEncoderOpusConfig::kMaxBitrateBps));
ossua1a040a2017-04-06 10:03:21 -0700139 if (bitrate != chosen_bitrate) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100140 RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate " << *bitrate
141 << " clamped to " << chosen_bitrate;
ossua1a040a2017-04-06 10:03:21 -0700142 }
143 return chosen_bitrate;
144 }
Mirko Bonadei675513b2017-11-09 11:09:25 +0100145 RTC_LOG(LS_WARNING) << "Invalid maxaveragebitrate \"" << *bitrate_param
146 << "\" replaced by default bitrate " << default_bitrate;
ossua1a040a2017-04-06 10:03:21 -0700147 }
148
149 return default_bitrate;
150}
151
152int GetChannelCount(const SdpAudioFormat& format) {
153 const auto param = GetFormatParameter(format, "stereo");
154 if (param == "1") {
155 return 2;
156 } else {
157 return 1;
158 }
159}
160
161int GetMaxPlaybackRate(const SdpAudioFormat& format) {
162 const auto param = GetFormatParameter<int>(format, "maxplaybackrate");
163 if (param && *param >= 8000) {
164 return std::min(*param, kDefaultMaxPlaybackRate);
165 }
166 return kDefaultMaxPlaybackRate;
167}
168
169int GetFrameSizeMs(const SdpAudioFormat& format) {
170 const auto ptime = GetFormatParameter<int>(format, "ptime");
171 if (ptime) {
172 // Pick the next highest supported frame length from
173 // kOpusSupportedFrameLengths.
174 for (const int supported_frame_length : kOpusSupportedFrameLengths) {
175 if (supported_frame_length >= *ptime) {
176 return supported_frame_length;
177 }
178 }
179 // If none was found, return the largest supported frame length.
180 return *(std::end(kOpusSupportedFrameLengths) - 1);
181 }
182
kwiberg96da0112017-06-30 04:23:22 -0700183 return AudioEncoderOpusConfig::kDefaultFrameSizeMs;
ossua1a040a2017-04-06 10:03:21 -0700184}
185
186void FindSupportedFrameLengths(int min_frame_length_ms,
187 int max_frame_length_ms,
188 std::vector<int>* out) {
189 out->clear();
190 std::copy_if(std::begin(kANASupportedFrameLengths),
191 std::end(kANASupportedFrameLengths), std::back_inserter(*out),
192 [&](int frame_length_ms) {
193 return frame_length_ms >= min_frame_length_ms &&
194 frame_length_ms <= max_frame_length_ms;
195 });
196 RTC_DCHECK(std::is_sorted(out->begin(), out->end()));
197}
198
kwiberg96da0112017-06-30 04:23:22 -0700199int GetBitrateBps(const AudioEncoderOpusConfig& config) {
200 RTC_DCHECK(config.IsOk());
201 return *config.bitrate_bps;
202}
203
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200204bool IsValidPacketLossRate(int value) {
205 return value >= 0 && value <= 100;
206}
207
208float ToFraction(int percent) {
209 return static_cast<float>(percent) / 100;
210}
211
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200212float GetMinPacketLossRate() {
213 constexpr char kPacketLossFieldTrial[] = "WebRTC-Audio-OpusMinPacketLossRate";
214 const bool use_opus_min_packet_loss_rate =
215 webrtc::field_trial::IsEnabled(kPacketLossFieldTrial);
216 if (use_opus_min_packet_loss_rate) {
217 const std::string field_trial_string =
218 webrtc::field_trial::FindFullName(kPacketLossFieldTrial);
219 constexpr int kDefaultMinPacketLossRate = 1;
220 int value = kDefaultMinPacketLossRate;
221 if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1 &&
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200222 !IsValidPacketLossRate(value)) {
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200223 RTC_LOG(LS_WARNING) << "Invalid parameter for " << kPacketLossFieldTrial
224 << ", using default value: "
225 << kDefaultMinPacketLossRate;
226 value = kDefaultMinPacketLossRate;
227 }
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200228 return ToFraction(value);
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200229 }
230 return 0.0;
231}
232
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200233std::unique_ptr<AudioEncoderOpusImpl::NewPacketLossRateOptimizer>
234GetNewPacketLossRateOptimizer() {
235 constexpr char kPacketLossOptimizationName[] =
236 "WebRTC-Audio-NewOpusPacketLossRateOptimization";
237 const bool use_new_packet_loss_optimization =
238 webrtc::field_trial::IsEnabled(kPacketLossOptimizationName);
239 if (use_new_packet_loss_optimization) {
240 const std::string field_trial_string =
241 webrtc::field_trial::FindFullName(kPacketLossOptimizationName);
242 int min_rate;
243 int max_rate;
244 float slope;
245 if (sscanf(field_trial_string.c_str(), "Enabled-%d-%d-%f", &min_rate,
246 &max_rate, &slope) == 3 &&
247 IsValidPacketLossRate(min_rate) && IsValidPacketLossRate(max_rate)) {
248 return absl::make_unique<
249 AudioEncoderOpusImpl::NewPacketLossRateOptimizer>(
250 ToFraction(min_rate), ToFraction(max_rate), slope);
251 }
252 RTC_LOG(LS_WARNING) << "Invalid parameters for "
253 << kPacketLossOptimizationName
254 << ", using default values.";
255 return absl::make_unique<
256 AudioEncoderOpusImpl::NewPacketLossRateOptimizer>();
257 }
258 return nullptr;
259}
260
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000261} // namespace
262
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200263AudioEncoderOpusImpl::NewPacketLossRateOptimizer::NewPacketLossRateOptimizer(
264 float min_packet_loss_rate,
265 float max_packet_loss_rate,
266 float slope)
267 : min_packet_loss_rate_(min_packet_loss_rate),
268 max_packet_loss_rate_(max_packet_loss_rate),
269 slope_(slope) {}
270
271float AudioEncoderOpusImpl::NewPacketLossRateOptimizer::OptimizePacketLossRate(
272 float packet_loss_rate) const {
273 packet_loss_rate = slope_ * packet_loss_rate;
274 return std::min(std::max(packet_loss_rate, min_packet_loss_rate_),
275 max_packet_loss_rate_);
276}
277
Karl Wiberg7275e182017-10-25 09:57:40 +0200278void AudioEncoderOpusImpl::AppendSupportedEncoders(
kwiberg96da0112017-06-30 04:23:22 -0700279 std::vector<AudioCodecSpec>* specs) {
Karl Wibergeb166972019-05-16 15:14:01 +0200280 const SdpAudioFormat fmt = {"opus",
281 kRtpTimestampRateHz,
282 2,
283 {{"minptime", "10"}, {"useinbandfec", "1"}}};
kwiberg96da0112017-06-30 04:23:22 -0700284 const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
285 specs->push_back({fmt, info});
286}
287
Karl Wiberg7275e182017-10-25 09:57:40 +0200288AudioCodecInfo AudioEncoderOpusImpl::QueryAudioEncoder(
kwiberg96da0112017-06-30 04:23:22 -0700289 const AudioEncoderOpusConfig& config) {
290 RTC_DCHECK(config.IsOk());
Karl Wibergeb166972019-05-16 15:14:01 +0200291 AudioCodecInfo info(kRtpTimestampRateHz, config.num_channels,
292 *config.bitrate_bps,
kwiberg96da0112017-06-30 04:23:22 -0700293 AudioEncoderOpusConfig::kMinBitrateBps,
294 AudioEncoderOpusConfig::kMaxBitrateBps);
295 info.allow_comfort_noise = false;
296 info.supports_network_adaption = true;
297 return info;
298}
299
Karl Wiberg7275e182017-10-25 09:57:40 +0200300std::unique_ptr<AudioEncoder> AudioEncoderOpusImpl::MakeAudioEncoder(
kwiberg96da0112017-06-30 04:23:22 -0700301 const AudioEncoderOpusConfig& config,
302 int payload_type) {
303 RTC_DCHECK(config.IsOk());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200304 return absl::make_unique<AudioEncoderOpusImpl>(config, payload_type);
kwiberg96da0112017-06-30 04:23:22 -0700305}
306
Danil Chapovalovb6021232018-06-19 13:26:36 +0200307absl::optional<AudioCodecInfo> AudioEncoderOpusImpl::QueryAudioEncoder(
ossua1a040a2017-04-06 10:03:21 -0700308 const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +0200309 if (absl::EqualsIgnoreCase(format.name, GetPayloadName()) &&
Karl Wibergeb166972019-05-16 15:14:01 +0200310 format.clockrate_hz == kRtpTimestampRateHz && format.num_channels == 2) {
ossua1a040a2017-04-06 10:03:21 -0700311 const size_t num_channels = GetChannelCount(format);
312 const int bitrate =
313 CalculateBitrate(GetMaxPlaybackRate(format), num_channels,
314 GetFormatParameter(format, "maxaveragebitrate"));
Karl Wibergeb166972019-05-16 15:14:01 +0200315 AudioCodecInfo info(kRtpTimestampRateHz, num_channels, bitrate,
kwiberg96da0112017-06-30 04:23:22 -0700316 AudioEncoderOpusConfig::kMinBitrateBps,
317 AudioEncoderOpusConfig::kMaxBitrateBps);
ossua1a040a2017-04-06 10:03:21 -0700318 info.allow_comfort_noise = false;
319 info.supports_network_adaption = true;
320
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100321 return info;
ossua1a040a2017-04-06 10:03:21 -0700322 }
Danil Chapovalovb6021232018-06-19 13:26:36 +0200323 return absl::nullopt;
ossua1a040a2017-04-06 10:03:21 -0700324}
325
Danil Chapovalovb6021232018-06-19 13:26:36 +0200326absl::optional<AudioEncoderOpusConfig> AudioEncoderOpusImpl::SdpToConfig(
ossua1a040a2017-04-06 10:03:21 -0700327 const SdpAudioFormat& format) {
Niels Möller2edab4c2018-10-22 09:48:08 +0200328 if (!absl::EqualsIgnoreCase(format.name, "opus") ||
Karl Wibergeb166972019-05-16 15:14:01 +0200329 format.clockrate_hz != kRtpTimestampRateHz || format.num_channels != 2) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200330 return absl::nullopt;
kwiberg96da0112017-06-30 04:23:22 -0700331 }
ossua1a040a2017-04-06 10:03:21 -0700332
kwiberg96da0112017-06-30 04:23:22 -0700333 AudioEncoderOpusConfig config;
ossua1a040a2017-04-06 10:03:21 -0700334 config.num_channels = GetChannelCount(format);
335 config.frame_size_ms = GetFrameSizeMs(format);
336 config.max_playback_rate_hz = GetMaxPlaybackRate(format);
337 config.fec_enabled = (GetFormatParameter(format, "useinbandfec") == "1");
338 config.dtx_enabled = (GetFormatParameter(format, "usedtx") == "1");
ossu0d6195d2017-04-28 07:33:18 -0700339 config.cbr_enabled = (GetFormatParameter(format, "cbr") == "1");
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100340 config.bitrate_bps =
ossua1a040a2017-04-06 10:03:21 -0700341 CalculateBitrate(config.max_playback_rate_hz, config.num_channels,
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100342 GetFormatParameter(format, "maxaveragebitrate"));
kwiberg96da0112017-06-30 04:23:22 -0700343 config.application = config.num_channels == 1
344 ? AudioEncoderOpusConfig::ApplicationMode::kVoip
345 : AudioEncoderOpusConfig::ApplicationMode::kAudio;
ossua1a040a2017-04-06 10:03:21 -0700346
347 constexpr int kMinANAFrameLength = kANASupportedFrameLengths[0];
348 constexpr int kMaxANAFrameLength =
349 kANASupportedFrameLengths[arraysize(kANASupportedFrameLengths) - 1];
kwiberg96da0112017-06-30 04:23:22 -0700350
ossua1a040a2017-04-06 10:03:21 -0700351 // For now, minptime and maxptime are only used with ANA. If ptime is outside
352 // of this range, it will get adjusted once ANA takes hold. Ideally, we'd know
353 // if ANA was to be used when setting up the config, and adjust accordingly.
354 const int min_frame_length_ms =
355 GetFormatParameter<int>(format, "minptime").value_or(kMinANAFrameLength);
356 const int max_frame_length_ms =
357 GetFormatParameter<int>(format, "maxptime").value_or(kMaxANAFrameLength);
358
359 FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
360 &config.supported_frame_lengths_ms);
kwiberg96da0112017-06-30 04:23:22 -0700361 RTC_DCHECK(config.IsOk());
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100362 return config;
kwiberg96da0112017-06-30 04:23:22 -0700363}
364
Danil Chapovalovb6021232018-06-19 13:26:36 +0200365absl::optional<int> AudioEncoderOpusImpl::GetNewComplexity(
kwiberg96da0112017-06-30 04:23:22 -0700366 const AudioEncoderOpusConfig& config) {
367 RTC_DCHECK(config.IsOk());
368 const int bitrate_bps = GetBitrateBps(config);
369 if (bitrate_bps >= config.complexity_threshold_bps -
370 config.complexity_threshold_window_bps &&
371 bitrate_bps <= config.complexity_threshold_bps +
372 config.complexity_threshold_window_bps) {
373 // Within the hysteresis window; make no change.
Danil Chapovalovb6021232018-06-19 13:26:36 +0200374 return absl::nullopt;
kwiberg96da0112017-06-30 04:23:22 -0700375 } else {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100376 return bitrate_bps <= config.complexity_threshold_bps
377 ? config.low_rate_complexity
378 : config.complexity;
kwiberg96da0112017-06-30 04:23:22 -0700379 }
ossua1a040a2017-04-06 10:03:21 -0700380}
381
Danil Chapovalovb6021232018-06-19 13:26:36 +0200382absl::optional<int> AudioEncoderOpusImpl::GetNewBandwidth(
Alex Luebseeb27652017-11-20 11:13:56 -0800383 const AudioEncoderOpusConfig& config,
384 OpusEncInst* inst) {
385 constexpr int kMinWidebandBitrate = 8000;
386 constexpr int kMaxNarrowbandBitrate = 9000;
387 constexpr int kAutomaticThreshold = 11000;
388 RTC_DCHECK(config.IsOk());
389 const int bitrate = GetBitrateBps(config);
390 if (bitrate > kAutomaticThreshold) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200391 return absl::optional<int>(OPUS_AUTO);
Alex Luebseeb27652017-11-20 11:13:56 -0800392 }
393 const int bandwidth = WebRtcOpus_GetBandwidth(inst);
394 RTC_DCHECK_GE(bandwidth, 0);
395 if (bitrate > kMaxNarrowbandBitrate && bandwidth < OPUS_BANDWIDTH_WIDEBAND) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200396 return absl::optional<int>(OPUS_BANDWIDTH_WIDEBAND);
Alex Luebseeb27652017-11-20 11:13:56 -0800397 } else if (bitrate < kMinWidebandBitrate &&
398 bandwidth > OPUS_BANDWIDTH_NARROWBAND) {
Danil Chapovalovb6021232018-06-19 13:26:36 +0200399 return absl::optional<int>(OPUS_BANDWIDTH_NARROWBAND);
Alex Luebseeb27652017-11-20 11:13:56 -0800400 }
Danil Chapovalovb6021232018-06-19 13:26:36 +0200401 return absl::optional<int>();
Alex Luebseeb27652017-11-20 11:13:56 -0800402}
403
Karl Wiberg7275e182017-10-25 09:57:40 +0200404class AudioEncoderOpusImpl::PacketLossFractionSmoother {
minyue7e304322016-10-12 05:00:55 -0700405 public:
michaelt92aef172017-04-18 00:11:48 -0700406 explicit PacketLossFractionSmoother()
407 : last_sample_time_ms_(rtc::TimeMillis()),
minyue7e304322016-10-12 05:00:55 -0700408 smoother_(kAlphaForPacketLossFractionSmoother) {}
409
410 // Gets the smoothed packet loss fraction.
411 float GetAverage() const {
412 float value = smoother_.filtered();
413 return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value;
414 }
415
416 // Add new observation to the packet loss fraction smoother.
417 void AddSample(float packet_loss_fraction) {
michaelt92aef172017-04-18 00:11:48 -0700418 int64_t now_ms = rtc::TimeMillis();
minyue7e304322016-10-12 05:00:55 -0700419 smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_),
420 packet_loss_fraction);
421 last_sample_time_ms_ = now_ms;
422 }
423
424 private:
minyue7e304322016-10-12 05:00:55 -0700425 int64_t last_sample_time_ms_;
426
427 // An exponential filter is used to smooth the packet loss fraction.
428 rtc::ExpFilter smoother_;
429};
430
Karl Wiberg7275e182017-10-25 09:57:40 +0200431AudioEncoderOpusImpl::AudioEncoderOpusImpl(const AudioEncoderOpusConfig& config,
432 int payload_type)
433 : AudioEncoderOpusImpl(
minyue-webrtc5d689102017-08-14 14:33:32 +0200434 config,
435 payload_type,
Mirko Bonadeie45c6882019-02-16 09:59:29 +0100436 [this](const std::string& config_string, RtcEventLog* event_log) {
minyue-webrtc5d689102017-08-14 14:33:32 +0200437 return DefaultAudioNetworkAdaptorCreator(config_string, event_log);
438 },
439 // We choose 5sec as initial time constant due to empirical data.
Karl Wiberg918f50c2018-07-05 11:40:33 +0200440 absl::make_unique<SmoothingFilterImpl>(5000)) {}
minyue-webrtc5d689102017-08-14 14:33:32 +0200441
Karl Wiberg7275e182017-10-25 09:57:40 +0200442AudioEncoderOpusImpl::AudioEncoderOpusImpl(
kwiberg96da0112017-06-30 04:23:22 -0700443 const AudioEncoderOpusConfig& config,
444 int payload_type,
minyue-webrtc5d689102017-08-14 14:33:32 +0200445 const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
michaelt566d8202017-01-12 10:17:38 -0800446 std::unique_ptr<SmoothingFilter> bitrate_smoother)
kwiberg96da0112017-06-30 04:23:22 -0700447 : payload_type_(payload_type),
minyue-webrtc5d689102017-08-14 14:33:32 +0200448 send_side_bwe_with_overhead_(
449 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100450 use_link_capacity_for_adaptation_(webrtc::field_trial::IsEnabled(
451 "WebRTC-Audio-LinkCapacityAdaptation")),
Alex Luebseeb27652017-11-20 11:13:56 -0800452 adjust_bandwidth_(
453 webrtc::field_trial::IsEnabled("WebRTC-AdjustOpusBandwidth")),
454 bitrate_changed_(true),
elad.alon0fe12162017-01-31 05:48:37 -0800455 packet_loss_rate_(0.0),
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200456 min_packet_loss_rate_(GetMinPacketLossRate()),
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200457 new_packet_loss_optimizer_(GetNewPacketLossRateOptimizer()),
minyue41b9c802016-10-06 07:13:54 -0700458 inst_(nullptr),
michaelt92aef172017-04-18 00:11:48 -0700459 packet_loss_fraction_smoother_(new PacketLossFractionSmoother()),
minyue-webrtc5d689102017-08-14 14:33:32 +0200460 audio_network_adaptor_creator_(audio_network_adaptor_creator),
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100461 bitrate_smoother_(std::move(bitrate_smoother)),
462 consecutive_dtx_frames_(0) {
minyue-webrtc5d689102017-08-14 14:33:32 +0200463 RTC_DCHECK(0 <= payload_type && payload_type <= 127);
kwiberg96da0112017-06-30 04:23:22 -0700464
465 // Sanity check of the redundant payload type field that we want to get rid
466 // of. See https://bugs.chromium.org/p/webrtc/issues/detail?id=7847
467 RTC_CHECK(config.payload_type == -1 || config.payload_type == payload_type);
468
henrikg91d6ede2015-09-17 00:24:34 -0700469 RTC_CHECK(RecreateEncoderInstance(config));
Jakob Ivarsson88b68ac2018-10-10 10:15:06 +0200470 SetProjectedPacketLossRate(packet_loss_rate_);
kwiberg12cfc9b2015-09-08 05:57:53 -0700471}
472
Karl Wiberg7275e182017-10-25 09:57:40 +0200473AudioEncoderOpusImpl::AudioEncoderOpusImpl(int payload_type,
474 const SdpAudioFormat& format)
475 : AudioEncoderOpusImpl(*SdpToConfig(format), payload_type) {}
ossua1a040a2017-04-06 10:03:21 -0700476
Karl Wiberg7275e182017-10-25 09:57:40 +0200477AudioEncoderOpusImpl::~AudioEncoderOpusImpl() {
henrikg91d6ede2015-09-17 00:24:34 -0700478 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700479}
480
Karl Wiberg7275e182017-10-25 09:57:40 +0200481int AudioEncoderOpusImpl::SampleRateHz() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700482 return kSampleRateHz;
483}
484
Karl Wiberg7275e182017-10-25 09:57:40 +0200485size_t AudioEncoderOpusImpl::NumChannels() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700486 return config_.num_channels;
487}
488
Karl Wibergeb166972019-05-16 15:14:01 +0200489int AudioEncoderOpusImpl::RtpTimestampRateHz() const {
490 return kRtpTimestampRateHz;
491}
492
Karl Wiberg7275e182017-10-25 09:57:40 +0200493size_t AudioEncoderOpusImpl::Num10MsFramesInNextPacket() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700494 return Num10msFramesPerPacket();
495}
496
Karl Wiberg7275e182017-10-25 09:57:40 +0200497size_t AudioEncoderOpusImpl::Max10MsFramesInAPacket() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700498 return Num10msFramesPerPacket();
499}
500
Karl Wiberg7275e182017-10-25 09:57:40 +0200501int AudioEncoderOpusImpl::GetTargetBitrate() const {
kwiberg96da0112017-06-30 04:23:22 -0700502 return GetBitrateBps(config_);
kwiberg12cfc9b2015-09-08 05:57:53 -0700503}
504
Karl Wiberg7275e182017-10-25 09:57:40 +0200505void AudioEncoderOpusImpl::Reset() {
henrikg91d6ede2015-09-17 00:24:34 -0700506 RTC_CHECK(RecreateEncoderInstance(config_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700507}
508
Karl Wiberg7275e182017-10-25 09:57:40 +0200509bool AudioEncoderOpusImpl::SetFec(bool enable) {
minyue41b9c802016-10-06 07:13:54 -0700510 if (enable) {
511 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
512 } else {
513 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
514 }
515 config_.fec_enabled = enable;
516 return true;
kwiberg12cfc9b2015-09-08 05:57:53 -0700517}
518
Karl Wiberg7275e182017-10-25 09:57:40 +0200519bool AudioEncoderOpusImpl::SetDtx(bool enable) {
minyue41b9c802016-10-06 07:13:54 -0700520 if (enable) {
521 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
522 } else {
523 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
524 }
525 config_.dtx_enabled = enable;
526 return true;
kwiberg12cfc9b2015-09-08 05:57:53 -0700527}
528
Karl Wiberg7275e182017-10-25 09:57:40 +0200529bool AudioEncoderOpusImpl::GetDtx() const {
ivoc85228d62016-07-27 04:53:47 -0700530 return config_.dtx_enabled;
531}
532
Karl Wiberg7275e182017-10-25 09:57:40 +0200533bool AudioEncoderOpusImpl::SetApplication(Application application) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700534 auto conf = config_;
535 switch (application) {
536 case Application::kSpeech:
kwiberg96da0112017-06-30 04:23:22 -0700537 conf.application = AudioEncoderOpusConfig::ApplicationMode::kVoip;
kwiberg12cfc9b2015-09-08 05:57:53 -0700538 break;
539 case Application::kAudio:
kwiberg96da0112017-06-30 04:23:22 -0700540 conf.application = AudioEncoderOpusConfig::ApplicationMode::kAudio;
kwiberg12cfc9b2015-09-08 05:57:53 -0700541 break;
542 }
543 return RecreateEncoderInstance(conf);
544}
545
Karl Wiberg7275e182017-10-25 09:57:40 +0200546void AudioEncoderOpusImpl::SetMaxPlaybackRate(int frequency_hz) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700547 auto conf = config_;
548 conf.max_playback_rate_hz = frequency_hz;
henrikg91d6ede2015-09-17 00:24:34 -0700549 RTC_CHECK(RecreateEncoderInstance(conf));
kwiberg12cfc9b2015-09-08 05:57:53 -0700550}
551
Karl Wiberg7275e182017-10-25 09:57:40 +0200552bool AudioEncoderOpusImpl::EnableAudioNetworkAdaptor(
minyue41b9c802016-10-06 07:13:54 -0700553 const std::string& config_string,
michaelt92aef172017-04-18 00:11:48 -0700554 RtcEventLog* event_log) {
michaeltbf279fc2017-01-13 06:02:29 -0800555 audio_network_adaptor_ =
michaelt92aef172017-04-18 00:11:48 -0700556 audio_network_adaptor_creator_(config_string, event_log);
minyue41b9c802016-10-06 07:13:54 -0700557 return audio_network_adaptor_.get() != nullptr;
558}
559
Karl Wiberg7275e182017-10-25 09:57:40 +0200560void AudioEncoderOpusImpl::DisableAudioNetworkAdaptor() {
minyue41b9c802016-10-06 07:13:54 -0700561 audio_network_adaptor_.reset(nullptr);
562}
563
Karl Wiberg7275e182017-10-25 09:57:40 +0200564void AudioEncoderOpusImpl::OnReceivedUplinkPacketLossFraction(
minyue41b9c802016-10-06 07:13:54 -0700565 float uplink_packet_loss_fraction) {
minyue7e304322016-10-12 05:00:55 -0700566 if (!audio_network_adaptor_) {
567 packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction);
568 float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage();
569 return SetProjectedPacketLossRate(average_fraction_loss);
570 }
minyue41b9c802016-10-06 07:13:54 -0700571 audio_network_adaptor_->SetUplinkPacketLossFraction(
572 uplink_packet_loss_fraction);
573 ApplyAudioNetworkAdaptor();
574}
575
Karl Wiberg7275e182017-10-25 09:57:40 +0200576void AudioEncoderOpusImpl::OnReceivedUplinkRecoverablePacketLossFraction(
elad.alondadb4dc2017-03-23 15:29:50 -0700577 float uplink_recoverable_packet_loss_fraction) {
578 if (!audio_network_adaptor_)
579 return;
580 audio_network_adaptor_->SetUplinkRecoverablePacketLossFraction(
581 uplink_recoverable_packet_loss_fraction);
582 ApplyAudioNetworkAdaptor();
583}
584
Karl Wiberg7275e182017-10-25 09:57:40 +0200585void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
michaelt566d8202017-01-12 10:17:38 -0800586 int target_audio_bitrate_bps,
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100587 absl::optional<int64_t> bwe_period_ms,
588 absl::optional<int64_t> link_capacity_allocation_bps) {
minyueeca373f2016-12-07 01:40:34 -0800589 if (audio_network_adaptor_) {
590 audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
michaelt566d8202017-01-12 10:17:38 -0800591 // We give smoothed bitrate allocation to audio network adaptor as
592 // the uplink bandwidth.
minyue-webrtcbf94fda2017-09-01 10:44:37 +0200593 // The BWE spikes should not affect the bitrate smoother more than 25%.
michaelt566d8202017-01-12 10:17:38 -0800594 // To simplify the calculations we use a step response as input signal.
595 // The step response of an exponential filter is
596 // u(t) = 1 - e^(-t / time_constant).
597 // In order to limit the affect of a BWE spike within 25% of its value
598 // before
minyue-webrtcbf94fda2017-09-01 10:44:37 +0200599 // the next BWE update, we would choose a time constant that fulfills
600 // 1 - e^(-bwe_period_ms / time_constant) < 0.25
601 // Then 4 * bwe_period_ms is a good choice.
602 if (bwe_period_ms)
603 bitrate_smoother_->SetTimeConstantMs(*bwe_period_ms * 4);
michaelt566d8202017-01-12 10:17:38 -0800604 bitrate_smoother_->AddSample(target_audio_bitrate_bps);
605
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100606 if (link_capacity_allocation_bps)
607 link_capacity_allocation_bps_ = link_capacity_allocation_bps;
608
minyueeca373f2016-12-07 01:40:34 -0800609 ApplyAudioNetworkAdaptor();
elad.alon0fe12162017-01-31 05:48:37 -0800610 } else if (send_side_bwe_with_overhead_) {
minyueeca373f2016-12-07 01:40:34 -0800611 if (!overhead_bytes_per_packet_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100612 RTC_LOG(LS_INFO)
Karl Wiberg7275e182017-10-25 09:57:40 +0200613 << "AudioEncoderOpusImpl: Overhead unknown, target audio bitrate "
minyueeca373f2016-12-07 01:40:34 -0800614 << target_audio_bitrate_bps << " bps is ignored.";
615 return;
616 }
617 const int overhead_bps = static_cast<int>(
618 *overhead_bytes_per_packet_ * 8 * 100 / Num10MsFramesInNextPacket());
kwiberg96da0112017-06-30 04:23:22 -0700619 SetTargetBitrate(
620 std::min(AudioEncoderOpusConfig::kMaxBitrateBps,
621 std::max(AudioEncoderOpusConfig::kMinBitrateBps,
622 target_audio_bitrate_bps - overhead_bps)));
minyueeca373f2016-12-07 01:40:34 -0800623 } else {
624 SetTargetBitrate(target_audio_bitrate_bps);
625 }
minyue41b9c802016-10-06 07:13:54 -0700626}
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100627void AudioEncoderOpusImpl::OnReceivedUplinkBandwidth(
628 int target_audio_bitrate_bps,
629 absl::optional<int64_t> bwe_period_ms) {
630 OnReceivedUplinkBandwidth(target_audio_bitrate_bps, bwe_period_ms,
631 absl::nullopt);
632}
633
634void AudioEncoderOpusImpl::OnReceivedUplinkAllocation(
635 BitrateAllocationUpdate update) {
636 OnReceivedUplinkBandwidth(update.target_bitrate.bps(), update.bwe_period.ms(),
637 update.link_capacity.bps());
638}
minyue41b9c802016-10-06 07:13:54 -0700639
Karl Wiberg7275e182017-10-25 09:57:40 +0200640void AudioEncoderOpusImpl::OnReceivedRtt(int rtt_ms) {
minyue41b9c802016-10-06 07:13:54 -0700641 if (!audio_network_adaptor_)
642 return;
643 audio_network_adaptor_->SetRtt(rtt_ms);
644 ApplyAudioNetworkAdaptor();
645}
646
Karl Wiberg7275e182017-10-25 09:57:40 +0200647void AudioEncoderOpusImpl::OnReceivedOverhead(
648 size_t overhead_bytes_per_packet) {
minyueeca373f2016-12-07 01:40:34 -0800649 if (audio_network_adaptor_) {
650 audio_network_adaptor_->SetOverhead(overhead_bytes_per_packet);
651 ApplyAudioNetworkAdaptor();
652 } else {
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100653 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
minyueeca373f2016-12-07 01:40:34 -0800654 }
655}
656
Karl Wiberg7275e182017-10-25 09:57:40 +0200657void AudioEncoderOpusImpl::SetReceiverFrameLengthRange(
658 int min_frame_length_ms,
659 int max_frame_length_ms) {
minyuea6f495c2016-10-24 09:19:14 -0700660 // Ensure that |SetReceiverFrameLengthRange| is called before
661 // |EnableAudioNetworkAdaptor|, otherwise we need to recreate
662 // |audio_network_adaptor_|, which is not a needed use case.
663 RTC_DCHECK(!audio_network_adaptor_);
ossua1a040a2017-04-06 10:03:21 -0700664 FindSupportedFrameLengths(min_frame_length_ms, max_frame_length_ms,
665 &config_.supported_frame_lengths_ms);
minyue41b9c802016-10-06 07:13:54 -0700666}
667
Karl Wiberg7275e182017-10-25 09:57:40 +0200668AudioEncoder::EncodedInfo AudioEncoderOpusImpl::EncodeImpl(
ossu10a029e2016-03-01 00:41:31 -0800669 uint32_t rtp_timestamp,
670 rtc::ArrayView<const int16_t> audio,
671 rtc::Buffer* encoded) {
michaelt566d8202017-01-12 10:17:38 -0800672 MaybeUpdateUplinkBandwidth();
ossu10a029e2016-03-01 00:41:31 -0800673
674 if (input_buffer_.empty())
675 first_timestamp_in_buffer_ = rtp_timestamp;
676
677 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
678 if (input_buffer_.size() <
679 (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
680 return EncodedInfo();
681 }
682 RTC_CHECK_EQ(input_buffer_.size(),
683 Num10msFramesPerPacket() * SamplesPer10msFrame());
684
ossu2903ba52016-04-18 06:14:33 -0700685 const size_t max_encoded_bytes = SufficientOutputBufferSize();
ossu10a029e2016-03-01 00:41:31 -0800686 EncodedInfo info;
Yves Gerey665174f2018-06-19 15:03:05 +0200687 info.encoded_bytes = encoded->AppendData(
688 max_encoded_bytes, [&](rtc::ArrayView<uint8_t> encoded) {
689 int status = WebRtcOpus_Encode(
690 inst_, &input_buffer_[0],
691 rtc::CheckedDivExact(input_buffer_.size(), config_.num_channels),
692 rtc::saturated_cast<int16_t>(max_encoded_bytes), encoded.data());
ossu10a029e2016-03-01 00:41:31 -0800693
Yves Gerey665174f2018-06-19 15:03:05 +0200694 RTC_CHECK_GE(status, 0); // Fails only if fed invalid data.
ossu10a029e2016-03-01 00:41:31 -0800695
Yves Gerey665174f2018-06-19 15:03:05 +0200696 return static_cast<size_t>(status);
697 });
ossu10a029e2016-03-01 00:41:31 -0800698 input_buffer_.clear();
699
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100700 bool dtx_frame = (info.encoded_bytes <= 2);
701
minyue41b9c802016-10-06 07:13:54 -0700702 // Will use new packet size for next encoding.
703 config_.frame_size_ms = next_frame_length_ms_;
704
Alex Luebseeb27652017-11-20 11:13:56 -0800705 if (adjust_bandwidth_ && bitrate_changed_) {
706 const auto bandwidth = GetNewBandwidth(config_, inst_);
707 if (bandwidth) {
708 RTC_CHECK_EQ(0, WebRtcOpus_SetBandwidth(inst_, *bandwidth));
709 }
710 bitrate_changed_ = false;
711 }
712
ossu10a029e2016-03-01 00:41:31 -0800713 info.encoded_timestamp = first_timestamp_in_buffer_;
kwiberg96da0112017-06-30 04:23:22 -0700714 info.payload_type = payload_type_;
ossu10a029e2016-03-01 00:41:31 -0800715 info.send_even_if_empty = true; // Allows Opus to send empty packets.
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100716 // After 20 DTX frames (MAX_CONSECUTIVE_DTX) Opus will send a frame
717 // coding the background noise. Avoid flagging this frame as speech
718 // (even though there is a probability of the frame being speech).
719 info.speech = !dtx_frame && (consecutive_dtx_frames_ != 20);
aleloi8bce67b2016-05-16 07:34:24 -0700720 info.encoder_type = CodecType::kOpus;
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100721
722 // Increase or reset DTX counter.
723 consecutive_dtx_frames_ = (dtx_frame) ? (consecutive_dtx_frames_ + 1) : (0);
724
ossu10a029e2016-03-01 00:41:31 -0800725 return info;
726}
727
Karl Wiberg7275e182017-10-25 09:57:40 +0200728size_t AudioEncoderOpusImpl::Num10msFramesPerPacket() const {
pkasting25702cb2016-01-08 13:50:27 -0800729 return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
kwiberg12cfc9b2015-09-08 05:57:53 -0700730}
731
Karl Wiberg7275e182017-10-25 09:57:40 +0200732size_t AudioEncoderOpusImpl::SamplesPer10msFrame() const {
kwiberg12cfc9b2015-09-08 05:57:53 -0700733 return rtc::CheckedDivExact(kSampleRateHz, 100) * config_.num_channels;
734}
735
Karl Wiberg7275e182017-10-25 09:57:40 +0200736size_t AudioEncoderOpusImpl::SufficientOutputBufferSize() const {
ossu2903ba52016-04-18 06:14:33 -0700737 // Calculate the number of bytes we expect the encoder to produce,
738 // then multiply by two to give a wide margin for error.
739 const size_t bytes_per_millisecond =
kwiberg96da0112017-06-30 04:23:22 -0700740 static_cast<size_t>(GetBitrateBps(config_) / (1000 * 8) + 1);
ossu2903ba52016-04-18 06:14:33 -0700741 const size_t approx_encoded_bytes =
742 Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
743 return 2 * approx_encoded_bytes;
744}
745
kwiberg12cfc9b2015-09-08 05:57:53 -0700746// If the given config is OK, recreate the Opus encoder instance with those
747// settings, save the config, and return true. Otherwise, do nothing and return
748// false.
Karl Wiberg7275e182017-10-25 09:57:40 +0200749bool AudioEncoderOpusImpl::RecreateEncoderInstance(
kwiberg96da0112017-06-30 04:23:22 -0700750 const AudioEncoderOpusConfig& config) {
kwiberg12cfc9b2015-09-08 05:57:53 -0700751 if (!config.IsOk())
752 return false;
elad.aloncfd88bb2017-03-14 02:50:46 -0700753 config_ = config;
kwiberg12cfc9b2015-09-08 05:57:53 -0700754 if (inst_)
henrikg91d6ede2015-09-17 00:24:34 -0700755 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
kwiberg12cfc9b2015-09-08 05:57:53 -0700756 input_buffer_.clear();
757 input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
kwiberg96da0112017-06-30 04:23:22 -0700758 RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(
759 &inst_, config.num_channels,
760 config.application ==
761 AudioEncoderOpusConfig::ApplicationMode::kVoip
762 ? 0
763 : 1));
Minyue Li9dac02d2019-01-18 11:09:47 +0100764 const int bitrate = GetBitrateBps(config);
765 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
766 RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000767 if (config.fec_enabled) {
henrikg91d6ede2015-09-17 00:24:34 -0700768 RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000769 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700770 RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
henrik.lundin@webrtc.org13980252015-01-29 16:08:40 +0000771 }
henrikg91d6ede2015-09-17 00:24:34 -0700772 RTC_CHECK_EQ(
773 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
henrik.lundin875862c2016-11-22 02:07:54 -0800774 // Use the default complexity if the start bitrate is within the hysteresis
775 // window.
kwiberg96da0112017-06-30 04:23:22 -0700776 complexity_ = GetNewComplexity(config).value_or(config.complexity);
henrik.lundin875862c2016-11-22 02:07:54 -0800777 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
Alex Luebseeb27652017-11-20 11:13:56 -0800778 bitrate_changed_ = true;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000779 if (config.dtx_enabled) {
henrikg91d6ede2015-09-17 00:24:34 -0700780 RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000781 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700782 RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000783 }
henrikg91d6ede2015-09-17 00:24:34 -0700784 RTC_CHECK_EQ(0,
785 WebRtcOpus_SetPacketLossRate(
786 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
ossu0d6195d2017-04-28 07:33:18 -0700787 if (config.cbr_enabled) {
788 RTC_CHECK_EQ(0, WebRtcOpus_EnableCbr(inst_));
789 } else {
790 RTC_CHECK_EQ(0, WebRtcOpus_DisableCbr(inst_));
791 }
minyue41b9c802016-10-06 07:13:54 -0700792 num_channels_to_encode_ = NumChannels();
793 next_frame_length_ms_ = config_.frame_size_ms;
kwiberg12cfc9b2015-09-08 05:57:53 -0700794 return true;
Karl Wibergdcccab32015-05-07 12:35:12 +0200795}
796
Karl Wiberg7275e182017-10-25 09:57:40 +0200797void AudioEncoderOpusImpl::SetFrameLength(int frame_length_ms) {
minyue41b9c802016-10-06 07:13:54 -0700798 next_frame_length_ms_ = frame_length_ms;
799}
800
Karl Wiberg7275e182017-10-25 09:57:40 +0200801void AudioEncoderOpusImpl::SetNumChannelsToEncode(
802 size_t num_channels_to_encode) {
kwibergaf476c72016-11-28 15:21:39 -0800803 RTC_DCHECK_GT(num_channels_to_encode, 0);
minyue41b9c802016-10-06 07:13:54 -0700804 RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels);
805
806 if (num_channels_to_encode_ == num_channels_to_encode)
807 return;
808
809 RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode));
810 num_channels_to_encode_ = num_channels_to_encode;
811}
812
Karl Wiberg7275e182017-10-25 09:57:40 +0200813void AudioEncoderOpusImpl::SetProjectedPacketLossRate(float fraction) {
Jakob Ivarsson83bd37c2018-10-15 09:54:46 +0200814 if (new_packet_loss_optimizer_) {
815 fraction = new_packet_loss_optimizer_->OptimizePacketLossRate(fraction);
816 } else {
817 fraction = OptimizePacketLossRate(fraction, packet_loss_rate_);
818 fraction = std::max(fraction, min_packet_loss_rate_);
819 }
820 if (packet_loss_rate_ != fraction) {
821 packet_loss_rate_ = fraction;
minyue4b9a2cb2016-11-30 06:49:59 -0800822 RTC_CHECK_EQ(
823 0, WebRtcOpus_SetPacketLossRate(
824 inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
825 }
826}
827
Karl Wiberg7275e182017-10-25 09:57:40 +0200828void AudioEncoderOpusImpl::SetTargetBitrate(int bits_per_second) {
Minyue Li9dac02d2019-01-18 11:09:47 +0100829 const int new_bitrate = rtc::SafeClamp<int>(
kwiberg96da0112017-06-30 04:23:22 -0700830 bits_per_second, AudioEncoderOpusConfig::kMinBitrateBps,
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100831 AudioEncoderOpusConfig::kMaxBitrateBps);
Minyue Li9dac02d2019-01-18 11:09:47 +0100832 if (config_.bitrate_bps && *config_.bitrate_bps != new_bitrate) {
833 config_.bitrate_bps = new_bitrate;
834 RTC_DCHECK(config_.IsOk());
835 const int bitrate = GetBitrateBps(config_);
836 RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
837 RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
838 bitrate_changed_ = true;
839 }
840
kwiberg96da0112017-06-30 04:23:22 -0700841 const auto new_complexity = GetNewComplexity(config_);
minyue4b9a2cb2016-11-30 06:49:59 -0800842 if (new_complexity && complexity_ != *new_complexity) {
843 complexity_ = *new_complexity;
844 RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
845 }
846}
847
Karl Wiberg7275e182017-10-25 09:57:40 +0200848void AudioEncoderOpusImpl::ApplyAudioNetworkAdaptor() {
minyue41b9c802016-10-06 07:13:54 -0700849 auto config = audio_network_adaptor_->GetEncoderRuntimeConfig();
minyue41b9c802016-10-06 07:13:54 -0700850
michaelt584c35a2016-12-27 08:21:29 -0800851 if (config.bitrate_bps)
852 SetTargetBitrate(*config.bitrate_bps);
853 if (config.frame_length_ms)
854 SetFrameLength(*config.frame_length_ms);
855 if (config.enable_fec)
856 SetFec(*config.enable_fec);
857 if (config.uplink_packet_loss_fraction)
858 SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction);
859 if (config.enable_dtx)
860 SetDtx(*config.enable_dtx);
861 if (config.num_channels)
862 SetNumChannelsToEncode(*config.num_channels);
minyue41b9c802016-10-06 07:13:54 -0700863}
864
865std::unique_ptr<AudioNetworkAdaptor>
Karl Wiberg7275e182017-10-25 09:57:40 +0200866AudioEncoderOpusImpl::DefaultAudioNetworkAdaptorCreator(
Mirko Bonadeie45c6882019-02-16 09:59:29 +0100867 const std::string& config_string,
michaelt92aef172017-04-18 00:11:48 -0700868 RtcEventLog* event_log) const {
minyue41b9c802016-10-06 07:13:54 -0700869 AudioNetworkAdaptorImpl::Config config;
michaeltbf279fc2017-01-13 06:02:29 -0800870 config.event_log = event_log;
minyue41b9c802016-10-06 07:13:54 -0700871 return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl(
kwiberg96da0112017-06-30 04:23:22 -0700872 config, ControllerManagerImpl::Create(
873 config_string, NumChannels(), supported_frame_lengths_ms(),
874 AudioEncoderOpusConfig::kMinBitrateBps,
875 num_channels_to_encode_, next_frame_length_ms_,
876 GetTargetBitrate(), config_.fec_enabled, GetDtx())));
minyue41b9c802016-10-06 07:13:54 -0700877}
878
Karl Wiberg7275e182017-10-25 09:57:40 +0200879void AudioEncoderOpusImpl::MaybeUpdateUplinkBandwidth() {
michaelt566d8202017-01-12 10:17:38 -0800880 if (audio_network_adaptor_) {
Sebastian Jansson8ac05cc2018-11-21 19:26:12 +0100881 if (use_link_capacity_for_adaptation_ && link_capacity_allocation_bps_) {
882 audio_network_adaptor_->SetUplinkBandwidth(
883 *link_capacity_allocation_bps_);
884 } else {
885 int64_t now_ms = rtc::TimeMillis();
886 if (!bitrate_smoother_last_update_time_ ||
887 now_ms - *bitrate_smoother_last_update_time_ >=
888 config_.uplink_bandwidth_update_interval_ms) {
889 absl::optional<float> smoothed_bitrate =
890 bitrate_smoother_->GetAverage();
891 if (smoothed_bitrate)
892 audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
893 bitrate_smoother_last_update_time_ = now_ms;
894 }
michaelt566d8202017-01-12 10:17:38 -0800895 }
896 }
897}
898
Karl Wiberg7275e182017-10-25 09:57:40 +0200899ANAStats AudioEncoderOpusImpl::GetANAStats() const {
ivoce1198e02017-09-08 08:13:19 -0700900 if (audio_network_adaptor_) {
901 return audio_network_adaptor_->GetStats();
902 }
903 return ANAStats();
904}
905
kwiberg@webrtc.org663fdd02014-10-29 07:28:36 +0000906} // namespace webrtc