Index: webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
index ae9dae2fbea4bc9e66d6a8b6826236258cc2ecab..29f85ac4704647e8d25039d068b0401a37b73851 100644 |
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
@@ -13,6 +13,7 @@ |
#include <algorithm> |
#include "webrtc/base/checks.h" |
+#include "webrtc/base/exp_filter.h" |
#include "webrtc/base/safe_conversions.h" |
#include "webrtc/common_types.h" |
#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h" |
@@ -24,11 +25,15 @@ namespace webrtc { |
namespace { |
-const int kSampleRateHz = 48000; |
-const int kMinBitrateBps = 500; |
-const int kMaxBitrateBps = 512000; |
+constexpr int kSampleRateHz = 48000; |
+constexpr int kMinBitrateBps = 500; |
+constexpr int kMaxBitrateBps = 512000; |
constexpr int kSupportedFrameLengths[] = {20, 60}; |
+// PacketLossFractionSmoother uses an exponential filter with a time constant |
+// of -1.0 / ln(0.9999) = 10000 ms. |
+constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f; |
+ |
AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { |
AudioEncoderOpus::Config config; |
config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48); |
@@ -82,6 +87,35 @@ double OptimizePacketLossRate(double new_loss_rate, double old_loss_rate) { |
} // namespace |
+class AudioEncoderOpus::PacketLossFractionSmoother { |
+ public: |
+ explicit PacketLossFractionSmoother(const Clock* clock) |
+ : clock_(clock), |
+ last_sample_time_ms_(clock_->TimeInMilliseconds()), |
+ smoother_(kAlphaForPacketLossFractionSmoother) {} |
+ |
+ // Gets the smoothed packet loss fraction. |
+ float GetAverage() const { |
+ float value = smoother_.filtered(); |
+ return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value; |
+ } |
+ |
+ // Add new observation to the packet loss fraction smoother. |
+ void AddSample(float packet_loss_fraction) { |
+ int64_t now_ms = clock_->TimeInMilliseconds(); |
+ smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_), |
+ packet_loss_fraction); |
+ last_sample_time_ms_ = now_ms; |
+ } |
+ |
+ private: |
+ const Clock* const clock_; |
+ int64_t last_sample_time_ms_; |
+ |
+ // An exponential filter is used to smooth the packet loss fraction. |
+ rtc::ExpFilter smoother_; |
+}; |
+ |
AudioEncoderOpus::Config::Config() = default; |
AudioEncoderOpus::Config::Config(const Config&) = default; |
AudioEncoderOpus::Config::~Config() = default; |
@@ -113,9 +147,11 @@ AudioEncoderOpus::AudioEncoderOpus( |
AudioNetworkAdaptorCreator&& audio_network_adaptor_creator) |
: packet_loss_rate_(0.0), |
inst_(nullptr), |
+ packet_loss_fraction_smoother_(new PacketLossFractionSmoother( |
+ config.clock ? config.clock : Clock::GetRealTimeClock())), |
audio_network_adaptor_creator_( |
audio_network_adaptor_creator |
- ? audio_network_adaptor_creator |
+ ? std::move(audio_network_adaptor_creator) |
: [this](const std::string& config_string, const Clock* clock) { |
return DefaultAudioNetworkAdaptorCreator(config_string, |
clock); |
@@ -234,8 +270,11 @@ void AudioEncoderOpus::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) { |
void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( |
float uplink_packet_loss_fraction) { |
- if (!audio_network_adaptor_) |
- return; |
+ if (!audio_network_adaptor_) { |
+ packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction); |
+ float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage(); |
+ return SetProjectedPacketLossRate(average_fraction_loss); |
+ } |
audio_network_adaptor_->SetUplinkPacketLossFraction( |
uplink_packet_loss_fraction); |
ApplyAudioNetworkAdaptor(); |
@@ -244,7 +283,7 @@ void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction( |
void AudioEncoderOpus::OnReceivedTargetAudioBitrate( |
int target_audio_bitrate_bps) { |
if (!audio_network_adaptor_) |
- return; |
+ return SetTargetBitrate(target_audio_bitrate_bps); |
audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); |
ApplyAudioNetworkAdaptor(); |
} |