Skip to content

Commit

Permalink
[wip] draft-688: Latency tuner refinements
Browse files Browse the repository at this point in the history
  • Loading branch information
gavv committed Jul 28, 2024
1 parent cc0efbc commit 7fc0a60
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 63 deletions.
8 changes: 4 additions & 4 deletions src/internal_modules/roc_audio/freq_estimator.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
namespace roc {
namespace audio {

//! FreqEstimator paremeter preset.
//! FreqEstimator parameters preset.
enum FreqEstimatorProfile {
//! Fast and responsive tuning.
//! Good for lower network latency and jitter.
Expand Down Expand Up @@ -68,9 +68,9 @@ struct FreqEstimatorConfig {
}
};

//! Evaluates sender's frequency to receivers's frequency ratio.
//! Evaluates sender's frequency to receiver's frequency ratio.
//! @remarks
//! We provide FreqEstimator with traget latency and periodically update it with
//! We provide FreqEstimator with target latency and periodically update it with
//! the actual latency. In response, FreqEstimator computes frequency coefficient,
//! the ratio of sender to receiver frequency. This coefficient is then set as
//! the scaling factor of the resampler, which in result compensates the frequency
Expand All @@ -86,7 +86,7 @@ class FreqEstimator : public core::NonCopyable<> {
packet::stream_timestamp_t target_latency,
dbgio::CsvDumper* dumper);

//! Get current frequecy coefficient.
//! Get current frequency coefficient.
float freq_coeff() const;

//! Compute new value of frequency coefficient.
Expand Down
103 changes: 51 additions & 52 deletions src/internal_modules/roc_audio/latency_tuner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ namespace {
const core::nanoseconds_t LogInterval = 5 * core::Second;

// Calculates latency decreasment step value such that
// if current latency equals exactly upper threshold value,
// after the decreasment it will get in the middle between threshold and estimated
// value.
// if current latency equals exactly upper threshold value, after the decreasment
// it will get in the middle between threshold and estimated value.
float upper_coef_to_step_lat_update_(const float x) {
return ((x + 1.f) / (x * 2.f));
}
Expand Down Expand Up @@ -578,58 +577,10 @@ void LatencyTuner::compute_scaling_(packet::stream_timestamp_diff_t latency) {
freq_coeff_ = std::max(freq_coeff_, 1.0f - freq_coeff_max_delta_);
}

void LatencyTuner::report_() {
if (stream_pos_ < report_pos_) {
return;
}

while (stream_pos_ >= report_pos_) {
report_pos_ += (packet::stream_timestamp_t)report_interval_;
}

roc_log(LogInfo,
"latency tuner:"
" e2e_latency=%ld(%.3fms) niq_latency=%ld(%.3fms) target_latency=%ld(%.3fms)"
" jitter=%.3fms stale=%ld(%.3fms)"
" fe=%.6f eff_fe=%.6f fe_stable=%s",
(long)e2e_latency_, sample_spec_.stream_timestamp_delta_2_ms(e2e_latency_),
(long)niq_latency_, sample_spec_.stream_timestamp_delta_2_ms(niq_latency_),
(long)target_latency_,
sample_spec_.stream_timestamp_delta_2_ms(target_latency_),
(double)link_metrics_.jitter / core::Millisecond, (long)niq_stalling_,
sample_spec_.stream_timestamp_delta_2_ms(niq_stalling_),
(double)(fe_ && freq_coeff_ > 0 ? fe_->freq_coeff() : 0), (double)freq_coeff_,
fe_ && fe_->is_stable() ? "true" : "false");

if (has_metrics_) {
roc_log(LogDebug,
"latency tuner:"
" cum_loss=%ld jitter=%.1fms"
" running_jitter(Max/Min)=%.1f/%.1fms"
" expected_packets=%ld",
(long)link_metrics_.lost_packets,
(double)link_metrics_.jitter / core::Millisecond,
(double)link_metrics_.max_jitter / core::Millisecond,
(double)link_metrics_.min_jitter / core::Millisecond,
(long)link_metrics_.expected_packets);
roc_log(LogDebug, "latency tuner: fec block duration=%.1fms",
(double)latency_metrics_.fec_block_duration / core::Millisecond);
}

if (sample_spec_.ns_2_stream_timestamp_delta(latency_metrics_.fec_block_duration)
>= max_latency_) {
roc_log(LogInfo,
"latency tuner: FEC block %.1fms is longer than the max "
"limit for latency %d(%.1fms)",
(double)latency_metrics_.fec_block_duration / core::Millisecond,
max_latency_, (double)max_latency_ / core::Millisecond);
}
}

// Decides if the latency should be adjusted and orders fe_ to do so if needed.
//
// 1. Decides to decrease latency if current value is greater than upper threshold,
// The target latency is supposed to change smoothely, so we just cut the current
// The target latency is supposed to change smoothly, so we just cut the current
// latency value by some percentage.
//
// 2. Decides to increase latency if it is lesser than lower threshold (which
Expand Down Expand Up @@ -750,6 +701,54 @@ void LatencyTuner::try_decrease_latency_(const core::nanoseconds_t estimate,
}
}

void LatencyTuner::report_() {
if (stream_pos_ < report_pos_) {
return;
}

while (stream_pos_ >= report_pos_) {
report_pos_ += (packet::stream_timestamp_t)report_interval_;
}

roc_log(LogInfo,
"latency tuner:"
" e2e_latency=%ld(%.3fms) niq_latency=%ld(%.3fms) target_latency=%ld(%.3fms)"
" jitter=%.3fms stale=%ld(%.3fms)"
" fe=%.6f eff_fe=%.6f fe_stable=%s",
(long)e2e_latency_, sample_spec_.stream_timestamp_delta_2_ms(e2e_latency_),
(long)niq_latency_, sample_spec_.stream_timestamp_delta_2_ms(niq_latency_),
(long)target_latency_,
sample_spec_.stream_timestamp_delta_2_ms(target_latency_),
(double)link_metrics_.jitter / core::Millisecond, (long)niq_stalling_,
sample_spec_.stream_timestamp_delta_2_ms(niq_stalling_),
(double)(fe_ && freq_coeff_ > 0 ? fe_->freq_coeff() : 0), (double)freq_coeff_,
fe_ && fe_->is_stable() ? "true" : "false");

if (has_metrics_) {
roc_log(LogDebug,
"latency tuner:"
" cum_loss=%ld jitter=%.1fms"
" running_jitter(Max/Min)=%.1f/%.1fms"
" expected_packets=%ld",
(long)link_metrics_.lost_packets,
(double)link_metrics_.jitter / core::Millisecond,
(double)link_metrics_.max_jitter / core::Millisecond,
(double)link_metrics_.min_jitter / core::Millisecond,
(long)link_metrics_.expected_packets);
roc_log(LogDebug, "latency tuner: fec block duration=%.1fms",
(double)latency_metrics_.fec_block_duration / core::Millisecond);
}

if (sample_spec_.ns_2_stream_timestamp_delta(latency_metrics_.fec_block_duration)
>= max_latency_) {
roc_log(LogInfo,
"latency tuner: FEC block %.1fms is longer than the max "
"limit for latency %d(%.1fms)",
(double)latency_metrics_.fec_block_duration / core::Millisecond,
max_latency_, (double)max_latency_ / core::Millisecond);
}
}

const char* latency_tuner_backend_to_str(LatencyTunerBackend backend) {
switch (backend) {
case LatencyTunerBackend_Default:
Expand Down
17 changes: 10 additions & 7 deletions src/internal_modules/roc_audio/latency_tuner.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,21 @@ class LatencyTuner : public core::NonCopyable<> {
private:
bool check_bounds_(packet::stream_timestamp_diff_t latency);
void compute_scaling_(packet::stream_timestamp_diff_t latency);
void report_();

// Decides if the latency should be adjusted and orders fe_ to do so if needed.
void update_target_latency_(core::nanoseconds_t max_jitter_ns,
core::nanoseconds_t mean_jitter_ns,
core::nanoseconds_t fec_block_ns);

void try_decrease_latency_(const core::nanoseconds_t estimate,
const core::nanoseconds_t now,
const core::nanoseconds_t cur_tl_ns);
void try_increase_latency_(const core::nanoseconds_t estimate,
const core::nanoseconds_t now,
const core::nanoseconds_t cur_tl_ns);

void report_();

core::Optional<FreqEstimator> fe_;

packet::stream_timestamp_t stream_pos_;
Expand Down Expand Up @@ -353,12 +362,6 @@ class LatencyTuner : public core::NonCopyable<> {
dbgio::CsvDumper* dumper_;

status::StatusCode init_status_;
void try_decrease_latency_(const core::nanoseconds_t estimate,
const core::nanoseconds_t now,
const core::nanoseconds_t cur_tl_ns);
void try_increase_latency_(const core::nanoseconds_t estimate,
const core::nanoseconds_t now,
const core::nanoseconds_t cur_tl_ns);
};

//! Get string name of latency backend.
Expand Down

0 comments on commit 7fc0a60

Please sign in to comment.