Embed Deceleration Target Level Offset Field Trial.
Bug: webrtc:10619 Change-Id: I4ef75ae03d6071bf84d2c1b6e50290ea26e83496 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/152663 Commit-Queue: Ruslan Burakov <kuddai@google.com> Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Minyue Li <minyue@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29169}
This commit is contained in:
committed by
Commit Bot
parent
ef85f2bdb8
commit
aa5a75d5e3
@ -39,6 +39,7 @@ constexpr int kMaxHistoryMs = 2000; // Oldest packet to include in history to
|
|||||||
// calculate relative packet arrival delay.
|
// calculate relative packet arrival delay.
|
||||||
constexpr int kDelayBuckets = 100;
|
constexpr int kDelayBuckets = 100;
|
||||||
constexpr int kBucketSizeMs = 20;
|
constexpr int kBucketSizeMs = 20;
|
||||||
|
constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8.
|
||||||
|
|
||||||
int PercentileToQuantile(double percentile) {
|
int PercentileToQuantile(double percentile) {
|
||||||
return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
|
return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
|
||||||
@ -79,29 +80,6 @@ DelayHistogramConfig GetDelayHistogramConfig() {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<int> GetDecelerationTargetLevelOffsetMs() {
|
|
||||||
constexpr char kDecelerationTargetLevelOffsetFieldTrial[] =
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset";
|
|
||||||
if (!webrtc::field_trial::IsEnabled(
|
|
||||||
kDecelerationTargetLevelOffsetFieldTrial)) {
|
|
||||||
return absl::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto field_trial_string = webrtc::field_trial::FindFullName(
|
|
||||||
kDecelerationTargetLevelOffsetFieldTrial);
|
|
||||||
int deceleration_target_level_offset_ms = -1;
|
|
||||||
sscanf(field_trial_string.c_str(), "Enabled-%d",
|
|
||||||
&deceleration_target_level_offset_ms);
|
|
||||||
if (deceleration_target_level_offset_ms >= 0) {
|
|
||||||
RTC_LOG(LS_INFO) << "NetEq deceleration_target_level_offset "
|
|
||||||
<< "in milliseconds "
|
|
||||||
<< deceleration_target_level_offset_ms;
|
|
||||||
// Convert into Q8.
|
|
||||||
return deceleration_target_level_offset_ms << 8;
|
|
||||||
}
|
|
||||||
return absl::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::optional<int> GetExtraDelayMs() {
|
absl::optional<int> GetExtraDelayMs() {
|
||||||
constexpr char kExtraDelayFieldTrial[] = "WebRTC-Audio-NetEqExtraDelay";
|
constexpr char kExtraDelayFieldTrial[] = "WebRTC-Audio-NetEqExtraDelay";
|
||||||
if (!webrtc::field_trial::IsEnabled(kExtraDelayFieldTrial)) {
|
if (!webrtc::field_trial::IsEnabled(kExtraDelayFieldTrial)) {
|
||||||
@ -153,14 +131,10 @@ DelayManager::DelayManager(size_t max_packets_in_buffer,
|
|||||||
frame_length_change_experiment_(
|
frame_length_change_experiment_(
|
||||||
field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
|
field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
|
||||||
enable_rtx_handling_(enable_rtx_handling),
|
enable_rtx_handling_(enable_rtx_handling),
|
||||||
deceleration_target_level_offset_ms_(
|
|
||||||
GetDecelerationTargetLevelOffsetMs()),
|
|
||||||
extra_delay_ms_(GetExtraDelayMs()) {
|
extra_delay_ms_(GetExtraDelayMs()) {
|
||||||
assert(peak_detector); // Should never be NULL.
|
assert(peak_detector); // Should never be NULL.
|
||||||
RTC_CHECK(histogram_);
|
RTC_CHECK(histogram_);
|
||||||
RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
|
RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
|
||||||
RTC_DCHECK(!deceleration_target_level_offset_ms_ ||
|
|
||||||
*deceleration_target_level_offset_ms_ >= 0);
|
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
@ -437,10 +411,10 @@ void DelayManager::BufferLimits(int target_level,
|
|||||||
// |target_level| is in Q8 already.
|
// |target_level| is in Q8 already.
|
||||||
*lower_limit = (target_level * 3) / 4;
|
*lower_limit = (target_level * 3) / 4;
|
||||||
|
|
||||||
if (deceleration_target_level_offset_ms_ && packet_len_ms_ > 0) {
|
if (packet_len_ms_ > 0) {
|
||||||
*lower_limit = std::max(
|
*lower_limit =
|
||||||
*lower_limit,
|
std::max(*lower_limit, target_level - kDecelerationTargetLevelOffsetMs /
|
||||||
target_level - *deceleration_target_level_offset_ms_ / packet_len_ms_);
|
packet_len_ms_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
|
int window_20ms = 0x7FFF; // Default large value for legacy bit-exactness.
|
||||||
@ -549,4 +523,5 @@ int DelayManager::MaxBufferTimeQ75() const {
|
|||||||
const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
|
const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
|
||||||
return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
|
return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -124,11 +124,6 @@ class DelayManager {
|
|||||||
return effective_minimum_delay_ms_;
|
return effective_minimum_delay_ms_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This accessor is only intended for testing purposes.
|
|
||||||
absl::optional<int> deceleration_target_level_offset_ms() const {
|
|
||||||
return deceleration_target_level_offset_ms_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These accessors are only intended for testing purposes.
|
// These accessors are only intended for testing purposes.
|
||||||
HistogramMode histogram_mode() const { return histogram_mode_; }
|
HistogramMode histogram_mode() const { return histogram_mode_; }
|
||||||
int histogram_quantile() const { return histogram_quantile_; }
|
int histogram_quantile() const { return histogram_quantile_; }
|
||||||
@ -204,11 +199,6 @@ class DelayManager {
|
|||||||
};
|
};
|
||||||
std::deque<PacketDelay> delay_history_;
|
std::deque<PacketDelay> delay_history_;
|
||||||
|
|
||||||
// When current buffer level is more than
|
|
||||||
// |deceleration_target_level_offset_ms_| below the target level, NetEq will
|
|
||||||
// impose deceleration to increase the buffer level. The value is in Q8, and
|
|
||||||
// measured in milliseconds.
|
|
||||||
const absl::optional<int> deceleration_target_level_offset_ms_;
|
|
||||||
const absl::optional<int> extra_delay_ms_;
|
const absl::optional<int> extra_delay_ms_;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(DelayManager);
|
RTC_DISALLOW_COPY_AND_ASSIGN(DelayManager);
|
||||||
|
|||||||
@ -594,54 +594,17 @@ TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) {
|
|||||||
InsertNextPacket();
|
InsertNextPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DelayManagerTest, DecelerationTargetLevelOffsetFieldTrial) {
|
|
||||||
{
|
|
||||||
test::ScopedFieldTrials field_trial(
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled-105/");
|
|
||||||
RecreateDelayManager();
|
|
||||||
EXPECT_EQ(dm_->deceleration_target_level_offset_ms().value(), 105 << 8);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Negative number.
|
|
||||||
test::ScopedFieldTrials field_trial(
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled--105/");
|
|
||||||
RecreateDelayManager();
|
|
||||||
EXPECT_FALSE(dm_->deceleration_target_level_offset_ms().has_value());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Disabled.
|
|
||||||
test::ScopedFieldTrials field_trial(
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Disabled/");
|
|
||||||
RecreateDelayManager();
|
|
||||||
EXPECT_FALSE(dm_->deceleration_target_level_offset_ms().has_value());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Float number.
|
|
||||||
test::ScopedFieldTrials field_trial(
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled-105.5/");
|
|
||||||
RecreateDelayManager();
|
|
||||||
EXPECT_EQ(dm_->deceleration_target_level_offset_ms().value(), 105 << 8);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Several numbers.
|
|
||||||
test::ScopedFieldTrials field_trial(
|
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled-20-40/");
|
|
||||||
RecreateDelayManager();
|
|
||||||
EXPECT_EQ(dm_->deceleration_target_level_offset_ms().value(), 20 << 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(DelayManagerTest, DecelerationTargetLevelOffset) {
|
TEST_F(DelayManagerTest, DecelerationTargetLevelOffset) {
|
||||||
// Border value where 1/4 target buffer level meets
|
SetPacketAudioLength(kFrameSizeMs);
|
||||||
// WebRTC-Audio-NetEqDecelerationTargetLevelOffset.
|
|
||||||
constexpr int kBoarderTargetLevel = 100 * 4;
|
// Deceleration target level offset follows the value hardcoded in
|
||||||
|
// delay_manager.cc.
|
||||||
|
constexpr int kDecelerationTargetLevelOffsetMs = 85 << 8; // In Q8.
|
||||||
|
// Border value where |x * 3/4 = target_level - x|.
|
||||||
|
constexpr int kBoarderTargetLevel = kDecelerationTargetLevelOffsetMs * 4;
|
||||||
{
|
{
|
||||||
// Test that for a low target level, default behaviour is intact.
|
// Test that for a low target level, default behaviour is intact.
|
||||||
test::ScopedFieldTrials field_trial(
|
const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs - 1;
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled-100/");
|
|
||||||
const int target_level_ms = ((kBoarderTargetLevel - 1) << 8) / kFrameSizeMs;
|
|
||||||
RecreateDelayManager();
|
|
||||||
SetPacketAudioLength(kFrameSizeMs);
|
|
||||||
|
|
||||||
int lower, higher; // In Q8.
|
int lower, higher; // In Q8.
|
||||||
dm_->BufferLimits(target_level_ms, &lower, &higher);
|
dm_->BufferLimits(target_level_ms, &lower, &higher);
|
||||||
@ -653,32 +616,14 @@ TEST_F(DelayManagerTest, DecelerationTargetLevelOffset) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Test that for the high target level, |lower| is below target level by
|
// Test that for the high target level, |lower| is below target level by
|
||||||
// fixed constant (100 ms in this Field Trial setup).
|
// fixed |kOffset|.
|
||||||
test::ScopedFieldTrials field_trial(
|
const int target_level_ms = kBoarderTargetLevel / kFrameSizeMs + 1;
|
||||||
"WebRTC-Audio-NetEqDecelerationTargetLevelOffset/Enabled-100/");
|
|
||||||
const int target_level_ms = ((kBoarderTargetLevel + 1) << 8) / kFrameSizeMs;
|
|
||||||
RecreateDelayManager();
|
|
||||||
SetPacketAudioLength(kFrameSizeMs);
|
|
||||||
|
|
||||||
int lower, higher; // In Q8.
|
int lower, higher; // In Q8.
|
||||||
dm_->BufferLimits(target_level_ms, &lower, &higher);
|
dm_->BufferLimits(target_level_ms, &lower, &higher);
|
||||||
|
|
||||||
EXPECT_EQ(target_level_ms - ((100 << 8) / kFrameSizeMs), lower);
|
EXPECT_EQ(target_level_ms - kDecelerationTargetLevelOffsetMs / kFrameSizeMs,
|
||||||
EXPECT_EQ(target_level_ms, higher);
|
lower);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Test that for the high target level, without Field Trial the behaviour
|
|
||||||
// will remain the same.
|
|
||||||
const int target_level_ms = ((kBoarderTargetLevel + 1) << 8) / kFrameSizeMs;
|
|
||||||
RecreateDelayManager();
|
|
||||||
SetPacketAudioLength(kFrameSizeMs);
|
|
||||||
|
|
||||||
int lower, higher; // In Q8.
|
|
||||||
dm_->BufferLimits(target_level_ms, &lower, &higher);
|
|
||||||
|
|
||||||
// Default behaviour of taking 75% of target level.
|
|
||||||
EXPECT_EQ(target_level_ms * 3 / 4, lower);
|
|
||||||
EXPECT_EQ(target_level_ms, higher);
|
EXPECT_EQ(target_level_ms, higher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user