Cleanup NetEq decision logic field trial.
Bug: webrtc:42223518
Change-Id: I2e5064109b9f0358e8e590e4aae6ebeb9d16bc3e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/358861
Reviewed-by: Tomas Lundqvist <tomasl@google.com>
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42746}
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index f68c057..4717144 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -21,10 +21,8 @@
#include "modules/audio_coding/neteq/packet_arrival_history.h"
#include "modules/audio_coding/neteq/packet_buffer.h"
#include "rtc_base/checks.h"
-#include "rtc_base/experiments/struct_parameters_parser.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
-#include "system_wrappers/include/field_trial.h"
namespace webrtc {
@@ -32,11 +30,11 @@
constexpr int kPostponeDecodingLevel = 50;
constexpr int kTargetLevelWindowMs = 100;
-constexpr int kMaxWaitForPacketMs = 100;
// The granularity of delay adjustments (accelerate/preemptive expand) is 15ms,
// but round up since the clock has a granularity of 10ms.
constexpr int kDelayAdjustmentGranularityMs = 20;
-constexpr int kReinitAfterExpandsMs = 1000;
+constexpr int kPacketHistorySizeMs = 2000;
+constexpr size_t kCngTimeoutMs = 1000;
std::unique_ptr<DelayManager> CreateDelayManager(
const NetEqController::Config& neteq_config) {
@@ -65,26 +63,6 @@
} // namespace
-DecisionLogic::Config::Config() {
- StructParametersParser::Create(
- "enable_stable_delay_mode", &enable_stable_delay_mode, //
- "combine_concealment_decision", &combine_concealment_decision, //
- "packet_history_size_ms", &packet_history_size_ms, //
- "cng_timeout_ms", &cng_timeout_ms, //
- "deceleration_target_level_offset_ms",
- &deceleration_target_level_offset_ms)
- ->Parse(webrtc::field_trial::FindFullName(
- "WebRTC-Audio-NetEqDecisionLogicConfig"));
- RTC_LOG(LS_INFO) << "NetEq decision logic config:"
- << " enable_stable_delay_mode=" << enable_stable_delay_mode
- << " combine_concealment_decision="
- << combine_concealment_decision
- << " packet_history_size_ms=" << packet_history_size_ms
- << " cng_timeout_ms=" << cng_timeout_ms.value_or(-1)
- << " deceleration_target_level_offset_ms="
- << deceleration_target_level_offset_ms;
-}
-
DecisionLogic::DecisionLogic(NetEqController::Config config)
: DecisionLogic(config,
CreateDelayManager(config),
@@ -97,11 +75,11 @@
std::unique_ptr<PacketArrivalHistory> packet_arrival_history)
: delay_manager_(std::move(delay_manager)),
buffer_level_filter_(std::move(buffer_level_filter)),
- packet_arrival_history_(packet_arrival_history
- ? std::move(packet_arrival_history)
- : std::make_unique<PacketArrivalHistory>(
- config.tick_timer,
- config_.packet_history_size_ms)),
+ packet_arrival_history_(
+ packet_arrival_history
+ ? std::move(packet_arrival_history)
+ : std::make_unique<PacketArrivalHistory>(config.tick_timer,
+ kPacketHistorySizeMs)),
tick_timer_(config.tick_timer),
disallow_time_stretching_(!config.allow_time_stretching),
timescale_countdown_(
@@ -136,8 +114,7 @@
if (prev_time_scale_) {
timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
}
- if (!IsCng(status.last_mode) &&
- !(config_.combine_concealment_decision && IsExpand(status.last_mode))) {
+ if (!IsCng(status.last_mode) && !IsExpand(status.last_mode)) {
FilterBufferLevel(status.packet_buffer_info.span_samples);
}
@@ -160,15 +137,6 @@
return NoPacket(status);
}
- // If the expand period was very long, reset NetEQ since it is likely that the
- // sender was restarted.
- if (!config_.combine_concealment_decision && IsExpand(status.last_mode) &&
- status.generated_noise_samples >
- static_cast<size_t>(kReinitAfterExpandsMs * sample_rate_khz_)) {
- *reset_decoder = true;
- return NetEq::Operation::kNormal;
- }
-
if (PostponeDecode(status)) {
return NoPacket(status);
}
@@ -190,13 +158,7 @@
}
int DecisionLogic::TargetLevelMs() const {
- int target_delay_ms = delay_manager_->TargetDelayMs();
- if (!config_.enable_stable_delay_mode) {
- target_delay_ms =
- std::max(target_delay_ms,
- static_cast<int>(packet_length_samples_ / sample_rate_khz_));
- }
- return target_delay_ms;
+ return delay_manager_->TargetDelayMs();
}
int DecisionLogic::UnlimitedTargetLevelMs() const {
@@ -290,9 +252,7 @@
return NetEq::Operation::kRfc3389CngNoPacket;
case NetEq::Mode::kCodecInternalCng: {
// Stop CNG after a timeout.
- if (config_.cng_timeout_ms &&
- status.generated_noise_samples >
- static_cast<size_t>(*config_.cng_timeout_ms * sample_rate_khz_)) {
+ if (status.generated_noise_samples > kCngTimeoutMs * sample_rate_khz_) {
return NetEq::Operation::kExpand;
}
return NetEq::Operation::kCodecInternalCng;
@@ -307,42 +267,20 @@
NetEqController::NetEqStatus status) {
if (!disallow_time_stretching_ && status.last_mode != NetEq::Mode::kExpand &&
!status.play_dtmf) {
- if (config_.enable_stable_delay_mode) {
- const int playout_delay_ms = GetPlayoutDelayMs(status);
- const int64_t low_limit = TargetLevelMs();
- const int64_t high_limit = low_limit +
- packet_arrival_history_->GetMaxDelayMs() +
- kDelayAdjustmentGranularityMs;
- if (playout_delay_ms >= high_limit * 4) {
- return NetEq::Operation::kFastAccelerate;
+ const int playout_delay_ms = GetPlayoutDelayMs(status);
+ const int64_t low_limit = TargetLevelMs();
+ const int64_t high_limit = low_limit +
+ packet_arrival_history_->GetMaxDelayMs() +
+ kDelayAdjustmentGranularityMs;
+ if (playout_delay_ms >= high_limit * 4) {
+ return NetEq::Operation::kFastAccelerate;
+ }
+ if (TimescaleAllowed()) {
+ if (playout_delay_ms >= high_limit) {
+ return NetEq::Operation::kAccelerate;
}
- if (TimescaleAllowed()) {
- if (playout_delay_ms >= high_limit) {
- return NetEq::Operation::kAccelerate;
- }
- if (playout_delay_ms < low_limit) {
- return NetEq::Operation::kPreemptiveExpand;
- }
- }
- } else {
- const int target_level_samples = TargetLevelMs() * sample_rate_khz_;
- const int low_limit = std::max(
- target_level_samples * 3 / 4,
- target_level_samples -
- config_.deceleration_target_level_offset_ms * sample_rate_khz_);
- const int high_limit = std::max(
- target_level_samples,
- low_limit + kDelayAdjustmentGranularityMs * sample_rate_khz_);
-
- const int buffer_level_samples =
- buffer_level_filter_->filtered_current_level();
- if (buffer_level_samples >= high_limit * 4)
- return NetEq::Operation::kFastAccelerate;
- if (TimescaleAllowed()) {
- if (buffer_level_samples >= high_limit)
- return NetEq::Operation::kAccelerate;
- if (buffer_level_samples < low_limit)
- return NetEq::Operation::kPreemptiveExpand;
+ if (playout_delay_ms < low_limit) {
+ return NetEq::Operation::kPreemptiveExpand;
}
}
}
@@ -354,35 +292,20 @@
// Required packet is not available, but a future packet is.
// Check if we should continue with an ongoing concealment because the new
// packet is too far into the future.
- if (config_.combine_concealment_decision || IsCng(status.last_mode)) {
- const int buffer_delay_samples =
- config_.combine_concealment_decision
- ? status.packet_buffer_info.span_samples_wait_time
- : status.packet_buffer_info.span_samples;
- const int buffer_delay_ms = buffer_delay_samples / sample_rate_khz_;
- const int high_limit = TargetLevelMs() + kTargetLevelWindowMs / 2;
- const int low_limit =
- std::max(0, TargetLevelMs() - kTargetLevelWindowMs / 2);
- const bool above_target_delay = buffer_delay_ms > high_limit;
- const bool below_target_delay = buffer_delay_ms < low_limit;
- if ((PacketTooEarly(status) && !above_target_delay) ||
- (below_target_delay && !config_.combine_concealment_decision)) {
- return NoPacket(status);
- }
- uint32_t timestamp_leap =
- status.next_packet->timestamp - status.target_timestamp;
- if (config_.combine_concealment_decision) {
- if (timestamp_leap != status.generated_noise_samples) {
- // The delay was adjusted, reinitialize the buffer level filter.
- buffer_level_filter_->SetFilteredBufferLevel(buffer_delay_samples);
- }
- } else {
- time_stretched_cn_samples_ =
- timestamp_leap - status.generated_noise_samples;
- }
- } else if (IsExpand(status.last_mode) && ShouldContinueExpand(status)) {
+ const int buffer_delay_samples =
+ status.packet_buffer_info.span_samples_wait_time;
+ const int buffer_delay_ms = buffer_delay_samples / sample_rate_khz_;
+ const int high_limit = TargetLevelMs() + kTargetLevelWindowMs / 2;
+ const bool above_target_delay = buffer_delay_ms > high_limit;
+ if ((PacketTooEarly(status) && !above_target_delay)) {
return NoPacket(status);
}
+ uint32_t timestamp_leap =
+ status.next_packet->timestamp - status.target_timestamp;
+ if (timestamp_leap != status.generated_noise_samples) {
+ // The delay was adjusted, reinitialize the buffer level filter.
+ buffer_level_filter_->SetFilteredBufferLevel(buffer_delay_samples);
+ }
// Time to play the next packet.
switch (status.last_mode) {
@@ -409,9 +332,7 @@
const size_t min_buffer_level_samples =
TargetLevelMs() * sample_rate_khz_ * kPostponeDecodingLevel / 100;
const size_t buffer_level_samples =
- config_.combine_concealment_decision
- ? status.packet_buffer_info.span_samples_wait_time
- : status.packet_buffer_info.span_samples;
+ status.packet_buffer_info.span_samples_wait_time;
if (buffer_level_samples >= min_buffer_level_samples) {
return false;
}
@@ -421,7 +342,7 @@
return false;
}
// Continue CNG until the buffer is at least at the minimum level.
- if (config_.combine_concealment_decision && IsCng(status.last_mode)) {
+ if (IsCng(status.last_mode)) {
return true;
}
// Only continue expand if the mute factor is low enough (otherwise the
@@ -433,32 +354,12 @@
return false;
}
-bool DecisionLogic::ReinitAfterExpands(
- NetEqController::NetEqStatus status) const {
- const uint32_t timestamp_leap =
- status.next_packet->timestamp - status.target_timestamp;
- return timestamp_leap >=
- static_cast<uint32_t>(kReinitAfterExpandsMs * sample_rate_khz_);
-}
-
bool DecisionLogic::PacketTooEarly(NetEqController::NetEqStatus status) const {
const uint32_t timestamp_leap =
status.next_packet->timestamp - status.target_timestamp;
return timestamp_leap > status.generated_noise_samples;
}
-bool DecisionLogic::MaxWaitForPacket(
- NetEqController::NetEqStatus status) const {
- return status.generated_noise_samples >=
- static_cast<size_t>(kMaxWaitForPacketMs * sample_rate_khz_);
-}
-
-bool DecisionLogic::ShouldContinueExpand(
- NetEqController::NetEqStatus status) const {
- return !ReinitAfterExpands(status) && !MaxWaitForPacket(status) &&
- PacketTooEarly(status) && UnderTargetLevel();
-}
-
int DecisionLogic::GetPlayoutDelayMs(
NetEqController::NetEqStatus status) const {
uint32_t playout_timestamp =
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index a6b02c6..7292148 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -140,29 +140,12 @@
// level, even though the next packet is available.
bool PostponeDecode(NetEqController::NetEqStatus status) const;
- // Checks if the timestamp leap is so long into the future that a reset due
- // to exceeding the expand limit will be done.
- bool ReinitAfterExpands(NetEqController::NetEqStatus status) const;
-
// Checks if we still have not done enough expands to cover the distance from
// the last decoded packet to the next available packet.
bool PacketTooEarly(NetEqController::NetEqStatus status) const;
- bool MaxWaitForPacket(NetEqController::NetEqStatus status) const;
- bool ShouldContinueExpand(NetEqController::NetEqStatus status) const;
+
int GetPlayoutDelayMs(NetEqController::NetEqStatus status) const;
- // Runtime configurable options through field trial
- // WebRTC-Audio-NetEqDecisionLogicConfig.
- struct Config {
- Config();
-
- bool enable_stable_delay_mode = true;
- bool combine_concealment_decision = true;
- int deceleration_target_level_offset_ms = 85;
- int packet_history_size_ms = 2000;
- absl::optional<int> cng_timeout_ms = 1000;
- };
- Config config_;
std::unique_ptr<DelayManager> delay_manager_;
std::unique_ptr<BufferLevelFilter> buffer_level_filter_;
std::unique_ptr<PacketArrivalHistory> packet_arrival_history_;