| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" | 11 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <iterator> | 14 #include <iterator> |
| 15 | 15 |
| 16 #include "webrtc/base/analytics/exp_filter.h" | 16 #include "webrtc/base/analytics/exp_filter.h" |
| 17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
| 19 #include "webrtc/base/safe_conversions.h" | 19 #include "webrtc/base/safe_conversions.h" |
| 20 #include "webrtc/base/timeutils.h" |
| 20 #include "webrtc/common_types.h" | 21 #include "webrtc/common_types.h" |
| 21 #include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adapto
r_impl.h" | 22 #include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adapto
r_impl.h" |
| 22 #include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h
" | 23 #include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h
" |
| 23 #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" | 24 #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" |
| 24 #include "webrtc/system_wrappers/include/clock.h" | |
| 25 #include "webrtc/system_wrappers/include/field_trial.h" | 25 #include "webrtc/system_wrappers/include/field_trial.h" |
| 26 | 26 |
| 27 namespace webrtc { | 27 namespace webrtc { |
| 28 | 28 |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 constexpr int kSampleRateHz = 48000; | 31 constexpr int kSampleRateHz = 48000; |
| 32 constexpr int kMinBitrateBps = 500; | 32 constexpr int kMinBitrateBps = 500; |
| 33 constexpr int kMaxBitrateBps = 512000; | 33 constexpr int kMaxBitrateBps = 512000; |
| 34 constexpr int kSupportedFrameLengths[] = {20, 60}; | 34 constexpr int kSupportedFrameLengths[] = {20, 60}; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 // Within the hysteresis window; make no change. | 165 // Within the hysteresis window; make no change. |
| 166 return rtc::Optional<int>(); | 166 return rtc::Optional<int>(); |
| 167 } | 167 } |
| 168 return bitrate_bps <= complexity_threshold_bps | 168 return bitrate_bps <= complexity_threshold_bps |
| 169 ? rtc::Optional<int>(low_rate_complexity) | 169 ? rtc::Optional<int>(low_rate_complexity) |
| 170 : rtc::Optional<int>(complexity); | 170 : rtc::Optional<int>(complexity); |
| 171 } | 171 } |
| 172 | 172 |
| 173 AudioEncoderOpus::AudioEncoderOpus( | 173 AudioEncoderOpus::AudioEncoderOpus( |
| 174 const Config& config, | 174 const Config& config, |
| 175 AudioNetworkAdaptorCreator&& audio_network_adaptor_creator) | 175 AudioNetworkAdaptorCreator&& audio_network_adaptor_creator, |
| 176 std::unique_ptr<SmoothingFilter> bitrate_smoother) |
| 176 : packet_loss_rate_(0.0), | 177 : packet_loss_rate_(0.0), |
| 177 inst_(nullptr), | 178 inst_(nullptr), |
| 178 packet_loss_fraction_smoother_(new PacketLossFractionSmoother( | 179 packet_loss_fraction_smoother_(new PacketLossFractionSmoother( |
| 179 config.clock ? config.clock : Clock::GetRealTimeClock())), | 180 config.clock)), |
| 180 audio_network_adaptor_creator_( | 181 audio_network_adaptor_creator_( |
| 181 audio_network_adaptor_creator | 182 audio_network_adaptor_creator |
| 182 ? std::move(audio_network_adaptor_creator) | 183 ? std::move(audio_network_adaptor_creator) |
| 183 : [this](const std::string& config_string, const Clock* clock) { | 184 : [this](const std::string& config_string, const Clock* clock) { |
| 184 return DefaultAudioNetworkAdaptorCreator(config_string, | 185 return DefaultAudioNetworkAdaptorCreator(config_string, |
| 185 clock); | 186 clock); |
| 186 }) { | 187 }), |
| 188 bitrate_smoother_(bitrate_smoother |
| 189 ? std::move(bitrate_smoother) : std::unique_ptr<SmoothingFilter>( |
| 190 // We choose 5sec as initial time constant due to empirical data. |
| 191 new SmoothingFilterImpl(5000, config.clock))) { |
| 187 RTC_CHECK(RecreateEncoderInstance(config)); | 192 RTC_CHECK(RecreateEncoderInstance(config)); |
| 188 } | 193 } |
| 189 | 194 |
| 190 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) | 195 AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) |
| 191 : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {} | 196 : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {} |
| 192 | 197 |
| 193 AudioEncoderOpus::~AudioEncoderOpus() { | 198 AudioEncoderOpus::~AudioEncoderOpus() { |
| 194 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); | 199 RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); |
| 195 } | 200 } |
| 196 | 201 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 const std::string& config_string, | 270 const std::string& config_string, |
| 266 const Clock* clock) { | 271 const Clock* clock) { |
| 267 audio_network_adaptor_ = audio_network_adaptor_creator_(config_string, clock); | 272 audio_network_adaptor_ = audio_network_adaptor_creator_(config_string, clock); |
| 268 return audio_network_adaptor_.get() != nullptr; | 273 return audio_network_adaptor_.get() != nullptr; |
| 269 } | 274 } |
| 270 | 275 |
| 271 void AudioEncoderOpus::DisableAudioNetworkAdaptor() { | 276 void AudioEncoderOpus::DisableAudioNetworkAdaptor() { |
| 272 audio_network_adaptor_.reset(nullptr); | 277 audio_network_adaptor_.reset(nullptr); |
| 273 } | 278 } |
| 274 | 279 |
| 275 void AudioEncoderOpus::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) { | |
| 276 if (!audio_network_adaptor_) | |
| 277 return; | |
| 278 audio_network_adaptor_->SetUplinkBandwidth(uplink_bandwidth_bps); | |
| 279 ApplyAudioNetworkAdaptor(); | |
| 280 } | |
| 281 | |
| 282 void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( | 280 void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( |
| 283 float uplink_packet_loss_fraction) { | 281 float uplink_packet_loss_fraction) { |
| 284 if (!audio_network_adaptor_) { | 282 if (!audio_network_adaptor_) { |
| 285 packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction); | 283 packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction); |
| 286 float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage(); | 284 float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage(); |
| 287 return SetProjectedPacketLossRate(average_fraction_loss); | 285 return SetProjectedPacketLossRate(average_fraction_loss); |
| 288 } | 286 } |
| 289 audio_network_adaptor_->SetUplinkPacketLossFraction( | 287 audio_network_adaptor_->SetUplinkPacketLossFraction( |
| 290 uplink_packet_loss_fraction); | 288 uplink_packet_loss_fraction); |
| 291 ApplyAudioNetworkAdaptor(); | 289 ApplyAudioNetworkAdaptor(); |
| 292 } | 290 } |
| 293 | 291 |
| 294 void AudioEncoderOpus::OnReceivedTargetAudioBitrate( | 292 void AudioEncoderOpus::OnReceivedUplinkBandwidth( |
| 295 int target_audio_bitrate_bps) { | 293 int target_audio_bitrate_bps, |
| 294 rtc::Optional<int64_t> probing_interval_ms) { |
| 296 if (audio_network_adaptor_) { | 295 if (audio_network_adaptor_) { |
| 297 audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); | 296 audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); |
| 297 // We give smoothed bitrate allocation to audio network adaptor as |
| 298 // the uplink bandwidth. |
| 299 // The probing spikes should not affect the bitrate smoother more than 25%. |
| 300 // To simplify the calculations we use a step response as input signal. |
| 301 // The step response of an exponential filter is |
| 302 // u(t) = 1 - e^(-t / time_constant). |
| 303 // In order to limit the affect of a BWE spike within 25% of its value |
| 304 // before |
| 305 // the next probing, we would choose a time constant that fulfills |
| 306 // 1 - e^(-probing_interval_ms / time_constant) < 0.25 |
| 307 // Then 4 * probing_interval_ms is a good choice. |
| 308 if (probing_interval_ms) |
| 309 bitrate_smoother_->SetTimeConstantMs(*probing_interval_ms * 4); |
| 310 bitrate_smoother_->AddSample(target_audio_bitrate_bps); |
| 311 |
| 298 ApplyAudioNetworkAdaptor(); | 312 ApplyAudioNetworkAdaptor(); |
| 299 } else if (webrtc::field_trial::FindFullName( | 313 } else if (webrtc::field_trial::FindFullName( |
| 300 "WebRTC-SendSideBwe-WithOverhead") == "Enabled") { | 314 "WebRTC-SendSideBwe-WithOverhead") == "Enabled") { |
| 301 if (!overhead_bytes_per_packet_) { | 315 if (!overhead_bytes_per_packet_) { |
| 302 LOG(LS_INFO) | 316 LOG(LS_INFO) |
| 303 << "AudioEncoderOpus: Overhead unknown, target audio bitrate " | 317 << "AudioEncoderOpus: Overhead unknown, target audio bitrate " |
| 304 << target_audio_bitrate_bps << " bps is ignored."; | 318 << target_audio_bitrate_bps << " bps is ignored."; |
| 305 return; | 319 return; |
| 306 } | 320 } |
| 307 const int overhead_bps = static_cast<int>( | 321 const int overhead_bps = static_cast<int>( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 frame_length_ms <= max_frame_length_ms; | 361 frame_length_ms <= max_frame_length_ms; |
| 348 }); | 362 }); |
| 349 RTC_DCHECK(std::is_sorted(config_.supported_frame_lengths_ms.begin(), | 363 RTC_DCHECK(std::is_sorted(config_.supported_frame_lengths_ms.begin(), |
| 350 config_.supported_frame_lengths_ms.end())); | 364 config_.supported_frame_lengths_ms.end())); |
| 351 } | 365 } |
| 352 | 366 |
| 353 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( | 367 AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( |
| 354 uint32_t rtp_timestamp, | 368 uint32_t rtp_timestamp, |
| 355 rtc::ArrayView<const int16_t> audio, | 369 rtc::ArrayView<const int16_t> audio, |
| 356 rtc::Buffer* encoded) { | 370 rtc::Buffer* encoded) { |
| 371 MaybeUpdateUplinkBandwidth(); |
| 357 | 372 |
| 358 if (input_buffer_.empty()) | 373 if (input_buffer_.empty()) |
| 359 first_timestamp_in_buffer_ = rtp_timestamp; | 374 first_timestamp_in_buffer_ = rtp_timestamp; |
| 360 | 375 |
| 361 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend()); | 376 input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend()); |
| 362 if (input_buffer_.size() < | 377 if (input_buffer_.size() < |
| 363 (Num10msFramesPerPacket() * SamplesPer10msFrame())) { | 378 (Num10msFramesPerPacket() * SamplesPer10msFrame())) { |
| 364 return EncodedInfo(); | 379 return EncodedInfo(); |
| 365 } | 380 } |
| 366 RTC_CHECK_EQ(input_buffer_.size(), | 381 RTC_CHECK_EQ(input_buffer_.size(), |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 const Clock* clock) const { | 529 const Clock* clock) const { |
| 515 AudioNetworkAdaptorImpl::Config config; | 530 AudioNetworkAdaptorImpl::Config config; |
| 516 config.clock = clock; | 531 config.clock = clock; |
| 517 return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl( | 532 return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl( |
| 518 config, ControllerManagerImpl::Create( | 533 config, ControllerManagerImpl::Create( |
| 519 config_string, NumChannels(), supported_frame_lengths_ms(), | 534 config_string, NumChannels(), supported_frame_lengths_ms(), |
| 520 num_channels_to_encode_, next_frame_length_ms_, | 535 num_channels_to_encode_, next_frame_length_ms_, |
| 521 GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock))); | 536 GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock))); |
| 522 } | 537 } |
| 523 | 538 |
| 539 void AudioEncoderOpus::MaybeUpdateUplinkBandwidth() { |
| 540 if (audio_network_adaptor_) { |
| 541 int64_t now_ms = rtc::TimeMillis(); |
| 542 if (!bitrate_smoother_last_update_time_ || |
| 543 now_ms - *bitrate_smoother_last_update_time_ >= |
| 544 config_.uplink_bandwidth_update_interval_ms) { |
| 545 rtc::Optional<float> smoothed_bitrate = bitrate_smoother_->GetAverage(); |
| 546 if (smoothed_bitrate) |
| 547 audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate); |
| 548 bitrate_smoother_last_update_time_ = rtc::Optional<int64_t>(now_ms); |
| 549 } |
| 550 } |
| 551 } |
| 552 |
| 524 } // namespace webrtc | 553 } // namespace webrtc |
| OLD | NEW |