Refactor NetEq delay manager logic.
- Removes dependence on sequence number for calculating target delay. - Changes target delay unit to milliseconds instead of number of packets. - Moves acceleration/preemptive expand thresholds to decision logic. Tests for this will be added in a follow up cl. Bug: webrtc:10333 Change-Id: If690aae4abf41ef1d9353f0ff01fb7d121cf8a26 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186265 Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32326}
This commit is contained in:
committed by
Commit Bot
parent
76d3e7a8d1
commit
f8e62fcb14
@ -27,6 +27,7 @@ namespace {
|
||||
|
||||
constexpr int kPostponeDecodingLevel = 50;
|
||||
constexpr int kDefaultTargetLevelWindowMs = 100;
|
||||
constexpr int kDecelerationTargetLevelOffsetMs = 85;
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -35,7 +36,6 @@ namespace webrtc {
|
||||
DecisionLogic::DecisionLogic(NetEqController::Config config)
|
||||
: delay_manager_(DelayManager::Create(config.max_packets_in_buffer,
|
||||
config.base_min_delay_ms,
|
||||
config.enable_rtx_handling,
|
||||
config.tick_timer)),
|
||||
tick_timer_(config.tick_timer),
|
||||
disallow_time_stretching_(!config.allow_time_stretching),
|
||||
@ -67,6 +67,7 @@ void DecisionLogic::Reset() {
|
||||
packet_length_samples_ = 0;
|
||||
sample_memory_ = 0;
|
||||
prev_time_scale_ = false;
|
||||
last_pack_cng_or_dtmf_ = true;
|
||||
timescale_countdown_.reset();
|
||||
num_consecutive_expands_ = 0;
|
||||
time_stretched_cn_samples_ = 0;
|
||||
@ -76,6 +77,7 @@ void DecisionLogic::SoftReset() {
|
||||
packet_length_samples_ = 0;
|
||||
sample_memory_ = 0;
|
||||
prev_time_scale_ = false;
|
||||
last_pack_cng_or_dtmf_ = true;
|
||||
timescale_countdown_ =
|
||||
tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1);
|
||||
time_stretched_cn_samples_ = 0;
|
||||
@ -158,12 +160,13 @@ NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status,
|
||||
const size_t current_span =
|
||||
estimate_dtx_delay_ ? status.packet_buffer_info.span_samples
|
||||
: status.packet_buffer_info.span_samples_no_dtx;
|
||||
const int target_level_samples =
|
||||
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
|
||||
if ((status.last_mode == NetEq::Mode::kExpand ||
|
||||
status.last_mode == NetEq::Mode::kCodecPlc) &&
|
||||
status.expand_mutefactor < 16384 / 2 &&
|
||||
current_span<static_cast<size_t>(delay_manager_->TargetLevel() *
|
||||
packet_length_samples_ *
|
||||
kPostponeDecodingLevel / 100)>> 8 &&
|
||||
current_span < static_cast<size_t>(target_level_samples *
|
||||
kPostponeDecodingLevel / 100) &&
|
||||
!status.packet_buffer_info.dtx_or_cng) {
|
||||
return NetEq::Operation::kExpand;
|
||||
}
|
||||
@ -195,41 +198,32 @@ void DecisionLogic::ExpandDecision(NetEq::Operation operation) {
|
||||
}
|
||||
}
|
||||
|
||||
absl::optional<int> DecisionLogic::PacketArrived(bool last_cng_or_dtmf,
|
||||
absl::optional<int> DecisionLogic::PacketArrived(bool is_cng_or_dtmf,
|
||||
size_t packet_length_samples,
|
||||
bool should_update_stats,
|
||||
uint16_t main_sequence_number,
|
||||
uint32_t main_timestamp,
|
||||
int fs_hz) {
|
||||
delay_manager_->LastDecodedWasCngOrDtmf(last_cng_or_dtmf);
|
||||
absl::optional<int> relative_delay;
|
||||
if (delay_manager_->last_pack_cng_or_dtmf() == 0) {
|
||||
// Calculate the total speech length carried in each packet.
|
||||
if (packet_length_samples > 0 &&
|
||||
packet_length_samples != packet_length_samples_) {
|
||||
packet_length_samples_ = packet_length_samples;
|
||||
delay_manager_->SetPacketAudioLength(
|
||||
rtc::dchecked_cast<int>((1000 * packet_length_samples) / fs_hz));
|
||||
}
|
||||
|
||||
// Update statistics.
|
||||
if (should_update_stats) {
|
||||
relative_delay =
|
||||
delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz);
|
||||
}
|
||||
} else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
|
||||
// This is first "normal" packet after CNG or DTMF.
|
||||
// Reset packet time counter and measure time until next packet,
|
||||
// but don't update statistics.
|
||||
delay_manager_->set_last_pack_cng_or_dtmf(0);
|
||||
delay_manager_->ResetPacketIatCount();
|
||||
if (is_cng_or_dtmf) {
|
||||
last_pack_cng_or_dtmf_ = true;
|
||||
return absl::nullopt;
|
||||
}
|
||||
if (!should_update_stats) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
if (packet_length_samples > 0 && fs_hz > 0 &&
|
||||
packet_length_samples != packet_length_samples_) {
|
||||
packet_length_samples_ = packet_length_samples;
|
||||
delay_manager_->SetPacketAudioLength(packet_length_samples_ * 1000 / fs_hz);
|
||||
}
|
||||
auto relative_delay = delay_manager_->Update(
|
||||
main_timestamp, fs_hz, /*reset=*/last_pack_cng_or_dtmf_);
|
||||
last_pack_cng_or_dtmf_ = false;
|
||||
return relative_delay;
|
||||
}
|
||||
|
||||
void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
|
||||
buffer_level_filter_.SetTargetBufferLevel(
|
||||
delay_manager_->base_target_level());
|
||||
buffer_level_filter_.SetTargetBufferLevel(delay_manager_->TargetDelayMs());
|
||||
|
||||
int time_stretched_samples = time_stretched_cn_samples_;
|
||||
if (prev_time_scale_) {
|
||||
@ -250,8 +244,8 @@ NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode,
|
||||
int32_t timestamp_diff = static_cast<int32_t>(
|
||||
static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
|
||||
available_timestamp);
|
||||
int32_t optimal_level_samp = static_cast<int32_t>(
|
||||
(delay_manager_->TargetLevel() * packet_length_samples_) >> 8);
|
||||
int optimal_level_samp =
|
||||
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
|
||||
const int64_t excess_waiting_time_samp =
|
||||
-static_cast<int64_t>(timestamp_diff) - optimal_level_samp;
|
||||
|
||||
@ -295,22 +289,26 @@ NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode,
|
||||
bool play_dtmf) {
|
||||
if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand &&
|
||||
!play_dtmf) {
|
||||
// Check criterion for time-stretching. The values are in number of packets
|
||||
// in Q8.
|
||||
int low_limit, high_limit;
|
||||
delay_manager_->BufferLimits(&low_limit, &high_limit);
|
||||
int buffer_level_packets = 0;
|
||||
if (packet_length_samples_ > 0) {
|
||||
buffer_level_packets =
|
||||
((1 << 8) * buffer_level_filter_.filtered_current_level()) /
|
||||
packet_length_samples_;
|
||||
}
|
||||
if (buffer_level_packets >= high_limit << 2)
|
||||
const int samples_per_ms = sample_rate_ / 1000;
|
||||
const int target_level_samples =
|
||||
delay_manager_->TargetDelayMs() * samples_per_ms;
|
||||
const int low_limit =
|
||||
std::max(target_level_samples * 3 / 4,
|
||||
target_level_samples -
|
||||
kDecelerationTargetLevelOffsetMs * samples_per_ms);
|
||||
// |higher_limit| is equal to |target_level|, but should at
|
||||
// least be 20 ms higher than |lower_limit|.
|
||||
const int high_limit =
|
||||
std::max(target_level_samples, low_limit + 20 * samples_per_ms);
|
||||
|
||||
const int buffer_level_samples =
|
||||
buffer_level_filter_.filtered_current_level();
|
||||
if (buffer_level_samples >= high_limit << 2)
|
||||
return NetEq::Operation::kFastAccelerate;
|
||||
if (TimescaleAllowed()) {
|
||||
if (buffer_level_packets >= high_limit)
|
||||
if (buffer_level_samples >= high_limit)
|
||||
return NetEq::Operation::kAccelerate;
|
||||
if (buffer_level_packets < low_limit)
|
||||
if (buffer_level_samples < low_limit)
|
||||
return NetEq::Operation::kPreemptiveExpand;
|
||||
}
|
||||
}
|
||||
@ -352,11 +350,11 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable(
|
||||
prev_mode == NetEq::Mode::kCodecInternalCng) {
|
||||
size_t cur_size_samples =
|
||||
estimate_dtx_delay_
|
||||
? cur_size_samples = span_samples_in_packet_buffer
|
||||
? span_samples_in_packet_buffer
|
||||
: num_packets_in_packet_buffer * decoder_frame_length;
|
||||
// Target level is in number of packets in Q8.
|
||||
const size_t target_level_samples =
|
||||
(delay_manager_->TargetLevel() * packet_length_samples_) >> 8;
|
||||
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
|
||||
const bool generated_enough_noise =
|
||||
static_cast<uint32_t>(generated_noise_samples + target_timestamp) >=
|
||||
available_timestamp;
|
||||
@ -406,13 +404,8 @@ NetEq::Operation DecisionLogic::FuturePacketAvailable(
|
||||
}
|
||||
|
||||
bool DecisionLogic::UnderTargetLevel() const {
|
||||
int buffer_level_packets = 0;
|
||||
if (packet_length_samples_ > 0) {
|
||||
buffer_level_packets =
|
||||
((1 << 8) * buffer_level_filter_.filtered_current_level()) /
|
||||
packet_length_samples_;
|
||||
}
|
||||
return buffer_level_packets <= delay_manager_->TargetLevel();
|
||||
return buffer_level_filter_.filtered_current_level() <
|
||||
delay_manager_->TargetDelayMs() * sample_rate_ / 1000;
|
||||
}
|
||||
|
||||
bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
|
||||
|
||||
Reference in New Issue
Block a user