From 88b68ace1732b757dcfd6d6bb4509d3769acb99d Mon Sep 17 00:00:00 2001 From: Jakob Ivarsson Date: Wed, 10 Oct 2018 10:15:06 +0200 Subject: [PATCH] Create field trial for setting a minimum value for Opus encoder packet loss rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:9848 Change-Id: I0663ee3af7729a220de7aff08cd74545e1a7409a Reviewed-on: https://webrtc-review.googlesource.com/c/104800 Reviewed-by: Minyue Li Commit-Queue: Jakob Ivarsson‎ Cr-Commit-Position: refs/heads/master@{#25081} --- .../codecs/opus/audio_encoder_opus.cc | 24 ++++++++++ .../codecs/opus/audio_encoder_opus.h | 1 + .../opus/audio_encoder_opus_unittest.cc | 45 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc index e6240e6982..a35ada80c8 100644 --- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc +++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc @@ -214,6 +214,27 @@ int GetBitrateBps(const AudioEncoderOpusConfig& config) { return *config.bitrate_bps; } +float GetMinPacketLossRate() { + constexpr char kPacketLossFieldTrial[] = "WebRTC-Audio-OpusMinPacketLossRate"; + const bool use_opus_min_packet_loss_rate = + webrtc::field_trial::IsEnabled(kPacketLossFieldTrial); + if (use_opus_min_packet_loss_rate) { + const std::string field_trial_string = + webrtc::field_trial::FindFullName(kPacketLossFieldTrial); + constexpr int kDefaultMinPacketLossRate = 1; + int value = kDefaultMinPacketLossRate; + if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1 && + (value < 0 || value > 100)) { + RTC_LOG(LS_WARNING) << "Invalid parameter for " << kPacketLossFieldTrial + << ", using default value: " + << kDefaultMinPacketLossRate; + value = kDefaultMinPacketLossRate; + } + return static_cast(value) / 100; + } + return 0.0; +} + } // namespace void AudioEncoderOpusImpl::AppendSupportedEncoders( @@ -402,6 +423,7 @@ AudioEncoderOpusImpl::AudioEncoderOpusImpl( webrtc::field_trial::IsEnabled("WebRTC-AdjustOpusBandwidth")), bitrate_changed_(true), packet_loss_rate_(0.0), + min_packet_loss_rate_(GetMinPacketLossRate()), inst_(nullptr), packet_loss_fraction_smoother_(new PacketLossFractionSmoother()), audio_network_adaptor_creator_(audio_network_adaptor_creator), @@ -414,6 +436,7 @@ AudioEncoderOpusImpl::AudioEncoderOpusImpl( RTC_CHECK(config.payload_type == -1 || config.payload_type == payload_type); RTC_CHECK(RecreateEncoderInstance(config)); + SetProjectedPacketLossRate(packet_loss_rate_); } AudioEncoderOpusImpl::AudioEncoderOpusImpl(const CodecInst& codec_inst) @@ -739,6 +762,7 @@ void AudioEncoderOpusImpl::SetNumChannelsToEncode( void AudioEncoderOpusImpl::SetProjectedPacketLossRate(float fraction) { float opt_loss_rate = OptimizePacketLossRate(fraction, packet_loss_rate_); + opt_loss_rate = std::max(opt_loss_rate, min_packet_loss_rate_); if (packet_loss_rate_ != opt_loss_rate) { packet_loss_rate_ = opt_loss_rate; RTC_CHECK_EQ( diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/modules/audio_coding/codecs/opus/audio_encoder_opus.h index ea4b2650bb..d34e22069d 100644 --- a/modules/audio_coding/codecs/opus/audio_encoder_opus.h +++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.h @@ -158,6 +158,7 @@ class AudioEncoderOpusImpl final : public AudioEncoder { const bool adjust_bandwidth_; bool bitrate_changed_; float packet_loss_rate_; + const float min_packet_loss_rate_; std::vector input_buffer_; OpusEncInst* inst_; uint32_t first_timestamp_in_buffer_; diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc index 7a6d5fda4b..0420c63739 100644 --- a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc +++ b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc @@ -272,6 +272,28 @@ TEST(AudioEncoderOpusTest, PacketLossRateOptimized) { // clang-format on } +TEST(AudioEncoderOpusTest, PacketLossRateLowerBounded) { + test::ScopedFieldTrials override_field_trails( + "WebRTC-Audio-OpusMinPacketLossRate/Enabled-5/"); + auto states = CreateCodec(1); + auto I = [](float a, float b) { return IntervalSteps(a, b, 10); }; + constexpr float eps = 1e-8f; + + // clang-format off + TestSetPacketLossRate(states.get(), I(0.00f , 0.01f - eps), 0.05f); + TestSetPacketLossRate(states.get(), I(0.01f + eps, 0.06f - eps), 0.05f); + TestSetPacketLossRate(states.get(), I(0.06f + eps, 0.11f - eps), 0.05f); + TestSetPacketLossRate(states.get(), I(0.11f + eps, 0.22f - eps), 0.10f); + TestSetPacketLossRate(states.get(), I(0.22f + eps, 1.00f ), 0.20f); + + TestSetPacketLossRate(states.get(), I(1.00f , 0.18f + eps), 0.20f); + TestSetPacketLossRate(states.get(), I(0.18f - eps, 0.09f + eps), 0.10f); + TestSetPacketLossRate(states.get(), I(0.09f - eps, 0.04f + eps), 0.05f); + TestSetPacketLossRate(states.get(), I(0.04f - eps, 0.01f + eps), 0.05f); + TestSetPacketLossRate(states.get(), I(0.01f - eps, 0.00f ), 0.05f); + // clang-format on +} + TEST(AudioEncoderOpusTest, SetReceiverFrameLengthRange) { auto states = CreateCodec(2); // Before calling to |SetReceiverFrameLengthRange|, @@ -446,6 +468,29 @@ TEST(AudioEncoderOpusTest, BitrateBounded) { EXPECT_EQ(kMaxBitrateBps, states->encoder->GetTargetBitrate()); } +TEST(AudioEncoderOpusTest, MinPacketLossRate) { + constexpr float kDefaultMinPacketLossRate = 0.01; + { + test::ScopedFieldTrials override_field_trails( + "WebRTC-Audio-OpusMinPacketLossRate/Enabled/"); + auto states = CreateCodec(1); + EXPECT_EQ(kDefaultMinPacketLossRate, states->encoder->packet_loss_rate()); + } + { + test::ScopedFieldTrials override_field_trails( + "WebRTC-Audio-OpusMinPacketLossRate/Enabled-200/"); + auto states = CreateCodec(1); + EXPECT_EQ(kDefaultMinPacketLossRate, states->encoder->packet_loss_rate()); + } + { + test::ScopedFieldTrials override_field_trails( + "WebRTC-Audio-OpusMinPacketLossRate/Enabled-50/"); + constexpr float kMinPacketLossRate = 0.5; + auto states = CreateCodec(1); + EXPECT_EQ(kMinPacketLossRate, states->encoder->packet_loss_rate()); + } +} + // Verifies that the complexity adaptation in the config works as intended. TEST(AudioEncoderOpusTest, ConfigComplexityAdaptation) { AudioEncoderOpusConfig config;