Line data Source code
1 : /*
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 :
11 : #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
12 :
13 : #include <algorithm>
14 : #include <iterator>
15 :
16 : #include "webrtc/base/checks.h"
17 : #include "webrtc/base/logging.h"
18 : #include "webrtc/base/numerics/exp_filter.h"
19 : #include "webrtc/base/safe_conversions.h"
20 : #include "webrtc/base/timeutils.h"
21 : #include "webrtc/common_types.h"
22 : #include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
23 : #include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
24 : #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
25 : #include "webrtc/system_wrappers/include/field_trial.h"
26 :
27 : namespace webrtc {
28 :
29 : namespace {
30 :
31 : constexpr int kSampleRateHz = 48000;
32 : constexpr int kMinBitrateBps = 500;
33 : constexpr int kMaxBitrateBps = 512000;
34 : constexpr int kSupportedFrameLengths[] = {20, 60};
35 :
36 : // PacketLossFractionSmoother uses an exponential filter with a time constant
37 : // of -1.0 / ln(0.9999) = 10000 ms.
38 : constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f;
39 :
40 0 : AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) {
41 0 : AudioEncoderOpus::Config config;
42 0 : config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
43 0 : config.num_channels = codec_inst.channels;
44 0 : config.bitrate_bps = rtc::Optional<int>(codec_inst.rate);
45 0 : config.payload_type = codec_inst.pltype;
46 0 : config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip
47 : : AudioEncoderOpus::kAudio;
48 0 : config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
49 : #if WEBRTC_OPUS_VARIABLE_COMPLEXITY
50 : config.low_rate_complexity = 9;
51 : #endif
52 0 : return config;
53 : }
54 :
55 : // Optimize the loss rate to configure Opus. Basically, optimized loss rate is
56 : // the input loss rate rounded down to various levels, because a robustly good
57 : // audio quality is achieved by lowering the packet loss down.
58 : // Additionally, to prevent toggling, margins are used, i.e., when jumping to
59 : // a loss rate from below, a higher threshold is used than jumping to the same
60 : // level from above.
61 0 : float OptimizePacketLossRate(float new_loss_rate, float old_loss_rate) {
62 0 : RTC_DCHECK_GE(new_loss_rate, 0.0f);
63 0 : RTC_DCHECK_LE(new_loss_rate, 1.0f);
64 0 : RTC_DCHECK_GE(old_loss_rate, 0.0f);
65 0 : RTC_DCHECK_LE(old_loss_rate, 1.0f);
66 0 : constexpr float kPacketLossRate20 = 0.20f;
67 0 : constexpr float kPacketLossRate10 = 0.10f;
68 0 : constexpr float kPacketLossRate5 = 0.05f;
69 0 : constexpr float kPacketLossRate1 = 0.01f;
70 0 : constexpr float kLossRate20Margin = 0.02f;
71 0 : constexpr float kLossRate10Margin = 0.01f;
72 0 : constexpr float kLossRate5Margin = 0.01f;
73 0 : if (new_loss_rate >=
74 0 : kPacketLossRate20 +
75 : kLossRate20Margin *
76 0 : (kPacketLossRate20 - old_loss_rate > 0 ? 1 : -1)) {
77 0 : return kPacketLossRate20;
78 0 : } else if (new_loss_rate >=
79 0 : kPacketLossRate10 +
80 : kLossRate10Margin *
81 0 : (kPacketLossRate10 - old_loss_rate > 0 ? 1 : -1)) {
82 0 : return kPacketLossRate10;
83 0 : } else if (new_loss_rate >=
84 0 : kPacketLossRate5 +
85 : kLossRate5Margin *
86 0 : (kPacketLossRate5 - old_loss_rate > 0 ? 1 : -1)) {
87 0 : return kPacketLossRate5;
88 0 : } else if (new_loss_rate >= kPacketLossRate1) {
89 0 : return kPacketLossRate1;
90 : } else {
91 0 : return 0.0f;
92 : }
93 : }
94 :
95 : } // namespace
96 :
97 : class AudioEncoderOpus::PacketLossFractionSmoother {
98 : public:
99 0 : explicit PacketLossFractionSmoother(const Clock* clock)
100 0 : : clock_(clock),
101 0 : last_sample_time_ms_(clock_->TimeInMilliseconds()),
102 0 : smoother_(kAlphaForPacketLossFractionSmoother) {}
103 :
104 : // Gets the smoothed packet loss fraction.
105 0 : float GetAverage() const {
106 0 : float value = smoother_.filtered();
107 0 : return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value;
108 : }
109 :
110 : // Add new observation to the packet loss fraction smoother.
111 0 : void AddSample(float packet_loss_fraction) {
112 0 : int64_t now_ms = clock_->TimeInMilliseconds();
113 0 : smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_),
114 0 : packet_loss_fraction);
115 0 : last_sample_time_ms_ = now_ms;
116 0 : }
117 :
118 : private:
119 : const Clock* const clock_;
120 : int64_t last_sample_time_ms_;
121 :
122 : // An exponential filter is used to smooth the packet loss fraction.
123 : rtc::ExpFilter smoother_;
124 : };
125 :
126 0 : AudioEncoderOpus::Config::Config() {
127 : #if WEBRTC_OPUS_VARIABLE_COMPLEXITY
128 : low_rate_complexity = 9;
129 : #endif
130 0 : }
131 : AudioEncoderOpus::Config::Config(const Config&) = default;
132 : AudioEncoderOpus::Config::~Config() = default;
133 : auto AudioEncoderOpus::Config::operator=(const Config&) -> Config& = default;
134 :
135 0 : bool AudioEncoderOpus::Config::IsOk() const {
136 0 : if (frame_size_ms <= 0 || frame_size_ms % 10 != 0)
137 0 : return false;
138 0 : if (num_channels != 1 && num_channels != 2)
139 0 : return false;
140 0 : if (bitrate_bps &&
141 0 : (*bitrate_bps < kMinBitrateBps || *bitrate_bps > kMaxBitrateBps))
142 0 : return false;
143 0 : if (complexity < 0 || complexity > 10)
144 0 : return false;
145 0 : if (low_rate_complexity < 0 || low_rate_complexity > 10)
146 0 : return false;
147 0 : return true;
148 : }
149 :
150 0 : int AudioEncoderOpus::Config::GetBitrateBps() const {
151 0 : RTC_DCHECK(IsOk());
152 0 : if (bitrate_bps)
153 0 : return *bitrate_bps; // Explicitly set value.
154 : else
155 0 : return num_channels == 1 ? 32000 : 64000; // Default value.
156 : }
157 :
158 0 : rtc::Optional<int> AudioEncoderOpus::Config::GetNewComplexity() const {
159 0 : RTC_DCHECK(IsOk());
160 0 : const int bitrate_bps = GetBitrateBps();
161 0 : if (bitrate_bps >=
162 0 : complexity_threshold_bps - complexity_threshold_window_bps &&
163 : bitrate_bps <=
164 0 : complexity_threshold_bps + complexity_threshold_window_bps) {
165 : // Within the hysteresis window; make no change.
166 0 : return rtc::Optional<int>();
167 : }
168 0 : return bitrate_bps <= complexity_threshold_bps
169 : ? rtc::Optional<int>(low_rate_complexity)
170 0 : : rtc::Optional<int>(complexity);
171 : }
172 :
173 0 : AudioEncoderOpus::AudioEncoderOpus(
174 : const Config& config,
175 : AudioNetworkAdaptorCreator&& audio_network_adaptor_creator,
176 0 : std::unique_ptr<SmoothingFilter> bitrate_smoother)
177 : : packet_loss_rate_(0.0),
178 : inst_(nullptr),
179 : packet_loss_fraction_smoother_(new PacketLossFractionSmoother(
180 0 : config.clock)),
181 : audio_network_adaptor_creator_(
182 : audio_network_adaptor_creator
183 0 : ? std::move(audio_network_adaptor_creator)
184 : : [this](const std::string& config_string,
185 : RtcEventLog* event_log,
186 0 : const Clock* clock) {
187 : return DefaultAudioNetworkAdaptorCreator(config_string,
188 : event_log, clock);
189 0 : }),
190 : bitrate_smoother_(bitrate_smoother
191 0 : ? std::move(bitrate_smoother) : std::unique_ptr<SmoothingFilter>(
192 : // We choose 5sec as initial time constant due to empirical data.
193 0 : new SmoothingFilterImpl(5000, config.clock))) {
194 0 : RTC_CHECK(RecreateEncoderInstance(config));
195 0 : }
196 :
197 0 : AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst)
198 0 : : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {}
199 :
200 0 : AudioEncoderOpus::~AudioEncoderOpus() {
201 0 : RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
202 0 : }
203 :
204 0 : int AudioEncoderOpus::SampleRateHz() const {
205 0 : return kSampleRateHz;
206 : }
207 :
208 0 : size_t AudioEncoderOpus::NumChannels() const {
209 0 : return config_.num_channels;
210 : }
211 :
212 0 : size_t AudioEncoderOpus::Num10MsFramesInNextPacket() const {
213 0 : return Num10msFramesPerPacket();
214 : }
215 :
216 0 : size_t AudioEncoderOpus::Max10MsFramesInAPacket() const {
217 0 : return Num10msFramesPerPacket();
218 : }
219 :
220 0 : int AudioEncoderOpus::GetTargetBitrate() const {
221 0 : return config_.GetBitrateBps();
222 : }
223 :
224 0 : void AudioEncoderOpus::Reset() {
225 0 : RTC_CHECK(RecreateEncoderInstance(config_));
226 0 : }
227 :
228 0 : bool AudioEncoderOpus::SetFec(bool enable) {
229 0 : if (enable) {
230 0 : RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
231 : } else {
232 0 : RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
233 : }
234 0 : config_.fec_enabled = enable;
235 0 : return true;
236 : }
237 :
238 0 : bool AudioEncoderOpus::SetDtx(bool enable) {
239 0 : if (enable) {
240 0 : RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
241 : } else {
242 0 : RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
243 : }
244 0 : config_.dtx_enabled = enable;
245 0 : return true;
246 : }
247 :
248 0 : bool AudioEncoderOpus::GetDtx() const {
249 0 : return config_.dtx_enabled;
250 : }
251 :
252 0 : bool AudioEncoderOpus::SetApplication(Application application) {
253 0 : auto conf = config_;
254 0 : switch (application) {
255 : case Application::kSpeech:
256 0 : conf.application = AudioEncoderOpus::kVoip;
257 0 : break;
258 : case Application::kAudio:
259 0 : conf.application = AudioEncoderOpus::kAudio;
260 0 : break;
261 : }
262 0 : return RecreateEncoderInstance(conf);
263 : }
264 :
265 0 : void AudioEncoderOpus::SetMaxPlaybackRate(int frequency_hz) {
266 0 : auto conf = config_;
267 0 : conf.max_playback_rate_hz = frequency_hz;
268 0 : RTC_CHECK(RecreateEncoderInstance(conf));
269 0 : }
270 :
271 0 : bool AudioEncoderOpus::EnableAudioNetworkAdaptor(
272 : const std::string& config_string,
273 : RtcEventLog* event_log,
274 : const Clock* clock) {
275 : audio_network_adaptor_ =
276 0 : audio_network_adaptor_creator_(config_string, event_log, clock);
277 0 : return audio_network_adaptor_.get() != nullptr;
278 : }
279 :
280 0 : void AudioEncoderOpus::DisableAudioNetworkAdaptor() {
281 0 : audio_network_adaptor_.reset(nullptr);
282 0 : }
283 :
284 0 : void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction(
285 : float uplink_packet_loss_fraction) {
286 0 : if (!audio_network_adaptor_) {
287 0 : packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction);
288 0 : float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage();
289 0 : return SetProjectedPacketLossRate(average_fraction_loss);
290 : }
291 0 : audio_network_adaptor_->SetUplinkPacketLossFraction(
292 0 : uplink_packet_loss_fraction);
293 0 : ApplyAudioNetworkAdaptor();
294 : }
295 :
296 0 : void AudioEncoderOpus::OnReceivedUplinkBandwidth(
297 : int target_audio_bitrate_bps,
298 : rtc::Optional<int64_t> probing_interval_ms) {
299 0 : if (audio_network_adaptor_) {
300 0 : audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
301 : // We give smoothed bitrate allocation to audio network adaptor as
302 : // the uplink bandwidth.
303 : // The probing spikes should not affect the bitrate smoother more than 25%.
304 : // To simplify the calculations we use a step response as input signal.
305 : // The step response of an exponential filter is
306 : // u(t) = 1 - e^(-t / time_constant).
307 : // In order to limit the affect of a BWE spike within 25% of its value
308 : // before
309 : // the next probing, we would choose a time constant that fulfills
310 : // 1 - e^(-probing_interval_ms / time_constant) < 0.25
311 : // Then 4 * probing_interval_ms is a good choice.
312 0 : if (probing_interval_ms)
313 0 : bitrate_smoother_->SetTimeConstantMs(*probing_interval_ms * 4);
314 0 : bitrate_smoother_->AddSample(target_audio_bitrate_bps);
315 :
316 0 : ApplyAudioNetworkAdaptor();
317 0 : } else if (webrtc::field_trial::FindFullName(
318 : "WebRTC-SendSideBwe-WithOverhead") == "Enabled") {
319 0 : if (!overhead_bytes_per_packet_) {
320 0 : LOG(LS_INFO)
321 0 : << "AudioEncoderOpus: Overhead unknown, target audio bitrate "
322 0 : << target_audio_bitrate_bps << " bps is ignored.";
323 0 : return;
324 : }
325 : const int overhead_bps = static_cast<int>(
326 0 : *overhead_bytes_per_packet_ * 8 * 100 / Num10MsFramesInNextPacket());
327 0 : SetTargetBitrate(std::min(
328 : kMaxBitrateBps,
329 0 : std::max(kMinBitrateBps, target_audio_bitrate_bps - overhead_bps)));
330 : } else {
331 0 : SetTargetBitrate(target_audio_bitrate_bps);
332 : }
333 : }
334 :
335 0 : void AudioEncoderOpus::OnReceivedRtt(int rtt_ms) {
336 0 : if (!audio_network_adaptor_)
337 0 : return;
338 0 : audio_network_adaptor_->SetRtt(rtt_ms);
339 0 : ApplyAudioNetworkAdaptor();
340 : }
341 :
342 0 : void AudioEncoderOpus::OnReceivedOverhead(size_t overhead_bytes_per_packet) {
343 0 : if (audio_network_adaptor_) {
344 0 : audio_network_adaptor_->SetOverhead(overhead_bytes_per_packet);
345 0 : ApplyAudioNetworkAdaptor();
346 : } else {
347 : overhead_bytes_per_packet_ =
348 0 : rtc::Optional<size_t>(overhead_bytes_per_packet);
349 : }
350 0 : }
351 :
352 0 : void AudioEncoderOpus::SetReceiverFrameLengthRange(int min_frame_length_ms,
353 : int max_frame_length_ms) {
354 : // Ensure that |SetReceiverFrameLengthRange| is called before
355 : // |EnableAudioNetworkAdaptor|, otherwise we need to recreate
356 : // |audio_network_adaptor_|, which is not a needed use case.
357 0 : RTC_DCHECK(!audio_network_adaptor_);
358 :
359 0 : config_.supported_frame_lengths_ms.clear();
360 : std::copy_if(std::begin(kSupportedFrameLengths),
361 : std::end(kSupportedFrameLengths),
362 : std::back_inserter(config_.supported_frame_lengths_ms),
363 0 : [&](int frame_length_ms) {
364 0 : return frame_length_ms >= min_frame_length_ms &&
365 0 : frame_length_ms <= max_frame_length_ms;
366 0 : });
367 0 : RTC_DCHECK(std::is_sorted(config_.supported_frame_lengths_ms.begin(),
368 0 : config_.supported_frame_lengths_ms.end()));
369 0 : }
370 :
371 0 : AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl(
372 : uint32_t rtp_timestamp,
373 : rtc::ArrayView<const int16_t> audio,
374 : rtc::Buffer* encoded) {
375 0 : MaybeUpdateUplinkBandwidth();
376 :
377 0 : if (input_buffer_.empty())
378 0 : first_timestamp_in_buffer_ = rtp_timestamp;
379 :
380 0 : input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
381 0 : if (input_buffer_.size() <
382 0 : (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
383 0 : return EncodedInfo();
384 : }
385 0 : RTC_CHECK_EQ(input_buffer_.size(),
386 0 : Num10msFramesPerPacket() * SamplesPer10msFrame());
387 :
388 0 : const size_t max_encoded_bytes = SufficientOutputBufferSize();
389 0 : EncodedInfo info;
390 0 : info.encoded_bytes =
391 0 : encoded->AppendData(
392 0 : max_encoded_bytes, [&] (rtc::ArrayView<uint8_t> encoded) {
393 0 : int status = WebRtcOpus_Encode(
394 0 : inst_, &input_buffer_[0],
395 : rtc::CheckedDivExact(input_buffer_.size(),
396 : config_.num_channels),
397 0 : rtc::saturated_cast<int16_t>(max_encoded_bytes),
398 0 : encoded.data());
399 :
400 0 : RTC_CHECK_GE(status, 0); // Fails only if fed invalid data.
401 :
402 0 : return static_cast<size_t>(status);
403 : });
404 0 : input_buffer_.clear();
405 :
406 : // Will use new packet size for next encoding.
407 0 : config_.frame_size_ms = next_frame_length_ms_;
408 :
409 0 : info.encoded_timestamp = first_timestamp_in_buffer_;
410 0 : info.payload_type = config_.payload_type;
411 0 : info.send_even_if_empty = true; // Allows Opus to send empty packets.
412 0 : info.speech = (info.encoded_bytes > 0);
413 0 : info.encoder_type = CodecType::kOpus;
414 0 : return info;
415 : }
416 :
417 0 : size_t AudioEncoderOpus::Num10msFramesPerPacket() const {
418 0 : return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
419 : }
420 :
421 0 : size_t AudioEncoderOpus::SamplesPer10msFrame() const {
422 0 : return rtc::CheckedDivExact(kSampleRateHz, 100) * config_.num_channels;
423 : }
424 :
425 0 : size_t AudioEncoderOpus::SufficientOutputBufferSize() const {
426 : // Calculate the number of bytes we expect the encoder to produce,
427 : // then multiply by two to give a wide margin for error.
428 : const size_t bytes_per_millisecond =
429 0 : static_cast<size_t>(config_.GetBitrateBps() / (1000 * 8) + 1);
430 : const size_t approx_encoded_bytes =
431 0 : Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
432 0 : return 2 * approx_encoded_bytes;
433 : }
434 :
435 : // If the given config is OK, recreate the Opus encoder instance with those
436 : // settings, save the config, and return true. Otherwise, do nothing and return
437 : // false.
438 0 : bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) {
439 0 : if (!config.IsOk())
440 0 : return false;
441 0 : if (inst_)
442 0 : RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
443 0 : input_buffer_.clear();
444 0 : input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
445 0 : RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, config.num_channels,
446 0 : config.application));
447 0 : RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config.GetBitrateBps()));
448 0 : if (config.fec_enabled) {
449 0 : RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
450 : } else {
451 0 : RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
452 : }
453 0 : RTC_CHECK_EQ(
454 0 : 0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
455 : // Use the default complexity if the start bitrate is within the hysteresis
456 : // window.
457 0 : complexity_ = config.GetNewComplexity().value_or(config.complexity);
458 0 : RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
459 0 : if (config.dtx_enabled) {
460 0 : RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
461 : } else {
462 0 : RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
463 : }
464 0 : RTC_CHECK_EQ(0,
465 : WebRtcOpus_SetPacketLossRate(
466 0 : inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
467 0 : config_ = config;
468 :
469 0 : num_channels_to_encode_ = NumChannels();
470 0 : next_frame_length_ms_ = config_.frame_size_ms;
471 0 : return true;
472 : }
473 :
474 0 : void AudioEncoderOpus::SetFrameLength(int frame_length_ms) {
475 0 : next_frame_length_ms_ = frame_length_ms;
476 0 : }
477 :
478 0 : void AudioEncoderOpus::SetNumChannelsToEncode(size_t num_channels_to_encode) {
479 0 : RTC_DCHECK_GT(num_channels_to_encode, 0);
480 0 : RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels);
481 :
482 0 : if (num_channels_to_encode_ == num_channels_to_encode)
483 0 : return;
484 :
485 0 : RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode));
486 0 : num_channels_to_encode_ = num_channels_to_encode;
487 : }
488 :
489 0 : void AudioEncoderOpus::SetProjectedPacketLossRate(float fraction) {
490 0 : float opt_loss_rate = OptimizePacketLossRate(fraction, packet_loss_rate_);
491 0 : if (packet_loss_rate_ != opt_loss_rate) {
492 0 : packet_loss_rate_ = opt_loss_rate;
493 0 : RTC_CHECK_EQ(
494 : 0, WebRtcOpus_SetPacketLossRate(
495 0 : inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
496 : }
497 0 : }
498 :
499 0 : void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) {
500 0 : config_.bitrate_bps = rtc::Optional<int>(
501 0 : std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps));
502 0 : RTC_DCHECK(config_.IsOk());
503 0 : RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps()));
504 0 : const auto new_complexity = config_.GetNewComplexity();
505 0 : if (new_complexity && complexity_ != *new_complexity) {
506 0 : complexity_ = *new_complexity;
507 0 : RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
508 : }
509 0 : }
510 :
511 0 : void AudioEncoderOpus::ApplyAudioNetworkAdaptor() {
512 0 : auto config = audio_network_adaptor_->GetEncoderRuntimeConfig();
513 0 : RTC_DCHECK(!config.frame_length_ms || *config.frame_length_ms == 20 ||
514 0 : *config.frame_length_ms == 60);
515 :
516 0 : if (config.bitrate_bps)
517 0 : SetTargetBitrate(*config.bitrate_bps);
518 0 : if (config.frame_length_ms)
519 0 : SetFrameLength(*config.frame_length_ms);
520 0 : if (config.enable_fec)
521 0 : SetFec(*config.enable_fec);
522 0 : if (config.uplink_packet_loss_fraction)
523 0 : SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction);
524 0 : if (config.enable_dtx)
525 0 : SetDtx(*config.enable_dtx);
526 0 : if (config.num_channels)
527 0 : SetNumChannelsToEncode(*config.num_channels);
528 0 : }
529 :
530 : std::unique_ptr<AudioNetworkAdaptor>
531 0 : AudioEncoderOpus::DefaultAudioNetworkAdaptorCreator(
532 : const std::string& config_string,
533 : RtcEventLog* event_log,
534 : const Clock* clock) const {
535 0 : AudioNetworkAdaptorImpl::Config config;
536 0 : config.clock = clock;
537 0 : config.event_log = event_log;
538 : return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl(
539 0 : config, ControllerManagerImpl::Create(
540 : config_string, NumChannels(), supported_frame_lengths_ms(),
541 0 : num_channels_to_encode_, next_frame_length_ms_,
542 0 : GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock)));
543 : }
544 :
545 0 : void AudioEncoderOpus::MaybeUpdateUplinkBandwidth() {
546 0 : if (audio_network_adaptor_) {
547 0 : int64_t now_ms = rtc::TimeMillis();
548 0 : if (!bitrate_smoother_last_update_time_ ||
549 0 : now_ms - *bitrate_smoother_last_update_time_ >=
550 0 : config_.uplink_bandwidth_update_interval_ms) {
551 0 : rtc::Optional<float> smoothed_bitrate = bitrate_smoother_->GetAverage();
552 0 : if (smoothed_bitrate)
553 0 : audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
554 0 : bitrate_smoother_last_update_time_ = rtc::Optional<int64_t>(now_ms);
555 : }
556 : }
557 0 : }
558 :
559 : } // namespace webrtc
|