diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc index 6b61555b47..349fdab9f1 100644 --- a/modules/audio_coding/neteq/decision_logic.cc +++ b/modules/audio_coding/neteq/decision_logic.cc @@ -21,8 +21,38 @@ #include "modules/audio_coding/neteq/packet_buffer.h" #include "modules/audio_coding/neteq/sync_buffer.h" #include "modules/include/module_common_types.h" +#include "rtc_base/logging.h" #include "system_wrappers/include/field_trial.h" +namespace { +constexpr char kPostponeDecodingFieldTrial[] = + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand"; + +int GetPostponeDecodingLevel() { + const bool enabled = + webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial); + if (!enabled) + return 0; + + constexpr int kDefaultPostponeDecodingLevel = 50; + const std::string field_trial_string = + webrtc::field_trial::FindFullName(kPostponeDecodingFieldTrial); + int value = -1; + if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1) { + if (value >= 0 && value <= 100) { + return value; + } else { + RTC_LOG(LS_WARNING) + << "Wrong value (" << value + << ") for postpone decoding after expand, using default (" + << kDefaultPostponeDecodingLevel << ")"; + } + } + return kDefaultPostponeDecodingLevel; +} + +} // namespace + namespace webrtc { DecisionLogic* DecisionLogic::Create(int fs_hz, @@ -59,8 +89,7 @@ DecisionLogic::DecisionLogic(int fs_hz, timescale_countdown_( tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)), num_consecutive_expands_(0), - postpone_decoding_after_expand_(field_trial::IsEnabled( - "WebRTC-Audio-NetEqPostponeDecodingAfterExpand")) { + postpone_decoding_level_(GetPostponeDecodingLevel()) { delay_manager_->set_streaming_mode(false); SetSampleRate(fs_hz, output_size_samples); } @@ -164,12 +193,13 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer, // if the mute factor is low enough (otherwise the expansion was short enough // to not be noticable). // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1. - if (postpone_decoding_after_expand_ && - (prev_mode == kModeExpand || prev_mode == kModeCodecPlc) && - !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_) && - cur_size_samples(delay_manager_->TargetLevel() * - packet_length_samples_)>> 8 && - expand.MuteFactor(0) < 16384 / 2) { + if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) && + expand.MuteFactor(0) < 16384 / 2 && + cur_size_samples < static_cast( + delay_manager_->TargetLevel() * packet_length_samples_ * + postpone_decoding_level_ / 100) >> 8 && + !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_)) { + RTC_DCHECK(webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial)); return kExpand; } diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h index 00b862008c..39761da070 100644 --- a/modules/audio_coding/neteq/decision_logic.h +++ b/modules/audio_coding/neteq/decision_logic.h @@ -109,6 +109,10 @@ class DecisionLogic final { } void set_prev_time_scale(bool value) { prev_time_scale_ = value; } + int postpone_decoding_level_for_test() const { + return postpone_decoding_level_; + } + private: // The value 5 sets maximum time-stretch rate to about 100 ms/s. static const int kMinTimescaleInterval = 5; @@ -181,7 +185,7 @@ class DecisionLogic final { bool disallow_time_stretching_; std::unique_ptr timescale_countdown_; int num_consecutive_expands_; - const bool postpone_decoding_after_expand_; + const int postpone_decoding_level_; RTC_DISALLOW_COPY_AND_ASSIGN(DecisionLogic); }; diff --git a/modules/audio_coding/neteq/decision_logic_unittest.cc b/modules/audio_coding/neteq/decision_logic_unittest.cc index 6929daadff..08720d1768 100644 --- a/modules/audio_coding/neteq/decision_logic_unittest.cc +++ b/modules/audio_coding/neteq/decision_logic_unittest.cc @@ -17,6 +17,7 @@ #include "modules/audio_coding/neteq/delay_peak_detector.h" #include "modules/audio_coding/neteq/packet_buffer.h" #include "modules/audio_coding/neteq/tick_timer.h" +#include "test/field_trial.h" #include "test/gtest.h" #include "test/mock_audio_decoder_factory.h" @@ -38,6 +39,62 @@ TEST(DecisionLogic, CreateAndDestroy) { delete logic; } +TEST(DecisionLogic, PostponeDecodingAfterExpansionSettings) { + constexpr int kDefaultPostponeDecodingLevel = 50; + constexpr int kFsHz = 8000; + constexpr int kOutputSizeSamples = kFsHz / 100; // Samples per 10 ms. + DecoderDatabase decoder_database( + new rtc::RefCountedObject, absl::nullopt); + TickTimer tick_timer; + PacketBuffer packet_buffer(10, &tick_timer); + DelayPeakDetector delay_peak_detector(&tick_timer); + DelayManager delay_manager(240, &delay_peak_detector, &tick_timer); + BufferLevelFilter buffer_level_filter; + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled/"); + DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, + &tick_timer); + EXPECT_EQ(kDefaultPostponeDecodingLevel, + logic.postpone_decoding_level_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-65/"); + DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, + &tick_timer); + EXPECT_EQ(65, logic.postpone_decoding_level_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Disabled/"); + DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, + &tick_timer); + EXPECT_EQ(0, logic.postpone_decoding_level_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled--1/"); + DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, + &tick_timer); + EXPECT_EQ(kDefaultPostponeDecodingLevel, + logic.postpone_decoding_level_for_test()); + } + { + test::ScopedFieldTrials field_trial( + "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-101/"); + DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database, + packet_buffer, &delay_manager, &buffer_level_filter, + &tick_timer); + EXPECT_EQ(kDefaultPostponeDecodingLevel, + logic.postpone_decoding_level_for_test()); + } +} + // TODO(hlundin): Write more tests. } // namespace webrtc