Add field trial and test for NetEq extra delay

Adding field trial WebRTC-Audio-NetEqExtraDelay with a parameter value
to set the extra delay in NetEq. This overrides the
extra_output_delay_ms parameter in NetEq::Config.

Bug: b/156734419
Change-Id: Iae7d439fafa3059494249959ac13a02de63d6b7a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176858
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31493}
This commit is contained in:
Henrik Lundin
2020-06-10 18:19:27 +02:00
committed by Commit Bot
parent 9276e2c39b
commit f7cba9f132
3 changed files with 55 additions and 6 deletions

View File

@ -51,6 +51,7 @@
#include "rtc_base/strings/audio_format_to_string.h" #include "rtc_base/strings/audio_format_to_string.h"
#include "rtc_base/trace_event.h" #include "rtc_base/trace_event.h"
#include "system_wrappers/include/clock.h" #include "system_wrappers/include/clock.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc { namespace webrtc {
namespace { namespace {
@ -73,6 +74,24 @@ std::unique_ptr<NetEqController> CreateNetEqController(
return controller_factory.CreateNetEqController(config); return controller_factory.CreateNetEqController(config);
} }
int GetDelayChainLengthMs(int config_extra_delay_ms) {
constexpr char kExtraDelayFieldTrial[] = "WebRTC-Audio-NetEqExtraDelay";
if (webrtc::field_trial::IsEnabled(kExtraDelayFieldTrial)) {
const auto field_trial_string =
webrtc::field_trial::FindFullName(kExtraDelayFieldTrial);
int extra_delay_ms = -1;
if (sscanf(field_trial_string.c_str(), "Enabled-%d", &extra_delay_ms) ==
1 &&
extra_delay_ms >= 0 && extra_delay_ms <= 2000) {
RTC_LOG(LS_INFO) << "Delay chain length set to " << extra_delay_ms
<< " ms in field trial";
return (extra_delay_ms / 10) * 10; // Rounding down to multiple of 10.
}
}
// Field trial not set, or invalid value read. Use value from config.
return config_extra_delay_ms;
}
} // namespace } // namespace
NetEqImpl::Dependencies::Dependencies( NetEqImpl::Dependencies::Dependencies(
@ -141,9 +160,9 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config,
tick_timer_.get()), tick_timer_.get()),
no_time_stretching_(config.for_test_no_time_stretching), no_time_stretching_(config.for_test_no_time_stretching),
enable_rtx_handling_(config.enable_rtx_handling), enable_rtx_handling_(config.enable_rtx_handling),
output_delay_chain_( output_delay_chain_ms_(
rtc::CheckedDivExact(config.extra_output_delay_ms, 10)), GetDelayChainLengthMs(config.extra_output_delay_ms)),
output_delay_chain_ms_(config.extra_output_delay_ms) { output_delay_chain_(rtc::CheckedDivExact(output_delay_chain_ms_, 10)) {
RTC_LOG(LS_INFO) << "NetEq config: " << config.ToString(); RTC_LOG(LS_INFO) << "NetEq config: " << config.ToString();
int fs = config.sample_rate_hz; int fs = config.sample_rate_hz;
if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) { if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) {

View File

@ -403,14 +403,14 @@ class NetEqImpl : public webrtc::NetEq {
rtc::BufferT<int16_t> concealment_audio_ RTC_GUARDED_BY(crit_sect_); rtc::BufferT<int16_t> concealment_audio_ RTC_GUARDED_BY(crit_sect_);
const bool enable_rtx_handling_ RTC_GUARDED_BY(crit_sect_); const bool enable_rtx_handling_ RTC_GUARDED_BY(crit_sect_);
// Data members used for adding extra delay to the output of NetEq. // Data members used for adding extra delay to the output of NetEq.
// The delay in ms (which is 10 times the number of elements in
// output_delay_chain_).
const int output_delay_chain_ms_ RTC_GUARDED_BY(crit_sect_);
// Vector of AudioFrames which contains the delayed audio. Accessed as a // Vector of AudioFrames which contains the delayed audio. Accessed as a
// circular buffer. // circular buffer.
std::vector<AudioFrame> output_delay_chain_ RTC_GUARDED_BY(crit_sect_); std::vector<AudioFrame> output_delay_chain_ RTC_GUARDED_BY(crit_sect_);
// Index into output_delay_chain_. // Index into output_delay_chain_.
size_t output_delay_chain_ix_ RTC_GUARDED_BY(crit_sect_) = 0; size_t output_delay_chain_ix_ RTC_GUARDED_BY(crit_sect_) = 0;
// The delay in ms (which is 10 times the number of elements in
// output_delay_chain_).
const int output_delay_chain_ms_ RTC_GUARDED_BY(crit_sect_);
// Did output_delay_chain_ get populated yet? // Did output_delay_chain_ get populated yet?
bool output_delay_chain_empty_ RTC_GUARDED_BY(crit_sect_) = true; bool output_delay_chain_empty_ RTC_GUARDED_BY(crit_sect_) = true;
// Contains the sample rate of the AudioFrame last emitted from the delay // Contains the sample rate of the AudioFrame last emitted from the delay

View File

@ -1253,5 +1253,35 @@ TEST(NetEqOutputDelayTest, RunTest) {
} }
} }
// Tests the extra output delay functionality of NetEq when configured via
// field trial.
TEST(NetEqOutputDelayTest, RunTestWithFieldTrial) {
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-NetEqExtraDelay/Enabled-50/");
constexpr int kExpectedDelayMs = 50;
std::vector<int16_t> output;
const auto result = DelayLineNetEqTest(0, &output);
// The base delay values are taken from the resuts of the non-delayed case in
// NetEqOutputDelayTest.RunTest above.
EXPECT_EQ(10 + kExpectedDelayMs, result.target_delay_ms);
EXPECT_EQ(24 + kExpectedDelayMs, result.filtered_current_delay_ms);
}
// Set a non-multiple-of-10 value in the field trial, and verify that we don't
// crash, and that the result is rounded down.
TEST(NetEqOutputDelayTest, RunTestWithFieldTrialOddValue) {
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-NetEqExtraDelay/Enabled-103/");
constexpr int kRoundedDelayMs = 100;
std::vector<int16_t> output;
const auto result = DelayLineNetEqTest(0, &output);
// The base delay values are taken from the resuts of the non-delayed case in
// NetEqOutputDelayTest.RunTest above.
EXPECT_EQ(10 + kRoundedDelayMs, result.target_delay_ms);
EXPECT_EQ(24 + kRoundedDelayMs, result.filtered_current_delay_ms);
}
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc