diff --git a/src/internal_modules/roc_audio/feedback_monitor.cpp b/src/internal_modules/roc_audio/feedback_monitor.cpp index 03bc67965..e3086e333 100644 --- a/src/internal_modules/roc_audio/feedback_monitor.cpp +++ b/src/internal_modules/roc_audio/feedback_monitor.cpp @@ -47,6 +47,8 @@ FeedbackMonitor::FeedbackMonitor(IFrameWriter& writer, , e2e_latency_(0) , has_niq_latency_(false) , has_e2e_latency_(false) + , jitter_(0) + , has_jitter_(false) , target_latency_(fe_input_ != audio::FreqEstimatorInput_Disable ? sample_spec.ns_2_stream_timestamp_delta(config.target_latency) : 0) @@ -105,6 +107,8 @@ FeedbackMonitorMetrics FeedbackMonitor::metrics() const { roc_panic_if(!is_valid()); FeedbackMonitorMetrics metrics; + metrics.jitter = sample_spec_.stream_timestamp_delta_2_ns(jitter_); + metrics.niq_latency = sample_spec_.stream_timestamp_delta_2_ns(niq_latency_); metrics.e2e_latency = sample_spec_.stream_timestamp_delta_2_ns(e2e_latency_); return metrics; @@ -128,6 +132,16 @@ void FeedbackMonitor::store(const FeedbackMonitorMetrics& metrics) { return; } + if (metrics.jitter != 0) { + jitter_ = sample_spec_.ns_2_stream_timestamp_delta(metrics.jitter); + has_jitter_ = true; + } + + if (metrics.niq_latency != 0) { + niq_latency_ = sample_spec_.ns_2_stream_timestamp_delta(metrics.niq_latency); + has_niq_latency_ = true; + } + if (metrics.e2e_latency != 0) { e2e_latency_ = sample_spec_.ns_2_stream_timestamp_delta(metrics.e2e_latency); has_e2e_latency_ = true; @@ -229,7 +243,7 @@ void FeedbackMonitor::report_() { return; } - if (!has_e2e_latency_ && !has_niq_latency_) { + if (!has_e2e_latency_ && !has_niq_latency_ && !has_jitter_) { return; } @@ -249,10 +263,12 @@ void FeedbackMonitor::report_() { roc_log(LogDebug, "feedback monitor:" " e2e_latency=%ld(%.3fms) niq_latency=%ld(%.3fms) target_latency=%ld(%.3fms)" + " jitter=%ld(%.3fms)" " fe=%.6f trim_fe=%.6f", (long)e2e_latency_, timestamp_to_ms(sample_spec_, e2e_latency_), (long)niq_latency_, timestamp_to_ms(sample_spec_, niq_latency_), - (long)target_latency_, timestamp_to_ms(sample_spec_, target_latency_), + (long)jitter_, timestamp_to_ms(sample_spec_, jitter_), (long)target_latency_, + timestamp_to_ms(sample_spec_, target_latency_), (double)(fe_ ? fe_->freq_coeff() : 0), (double)freq_coeff_); } diff --git a/src/internal_modules/roc_audio/feedback_monitor.h b/src/internal_modules/roc_audio/feedback_monitor.h index f8625b9c0..e7bb2053d 100644 --- a/src/internal_modules/roc_audio/feedback_monitor.h +++ b/src/internal_modules/roc_audio/feedback_monitor.h @@ -26,13 +26,24 @@ namespace audio { //! Metrics for feedback monitor. struct FeedbackMonitorMetrics { + //! Estimated interarrival jitter. + //! An estimate of the statistical variance of the RTP data packet + //! interarrival time. + core::nanoseconds_t jitter; + + //! Estimated network incoming queue latency. + //! An estimate of how much media is buffered in receiver packet queue. + core::nanoseconds_t niq_latency; + //! Estimated end-to-end latency. - //! An estimate of the time from recording a frame on sender to - //! playing it on receiver. + //! An estimate of the time from recording a frame on sender to playing it + //! on receiver. core::nanoseconds_t e2e_latency; FeedbackMonitorMetrics() - : e2e_latency(0) { + : jitter(0) + , niq_latency(0) + , e2e_latency(0) { } }; @@ -94,6 +105,9 @@ class FeedbackMonitor : public IFrameWriter, public core::NonCopyable<> { bool has_niq_latency_; bool has_e2e_latency_; + packet::stream_timestamp_diff_t jitter_; + bool has_jitter_; + const packet::stream_timestamp_diff_t target_latency_; const SampleSpec sample_spec_; diff --git a/src/internal_modules/roc_pipeline/sender_session.cpp b/src/internal_modules/roc_pipeline/sender_session.cpp index 388029a4a..aac659a9c 100644 --- a/src/internal_modules/roc_pipeline/sender_session.cpp +++ b/src/internal_modules/roc_pipeline/sender_session.cpp @@ -295,6 +295,8 @@ SenderSession::notify_send_stream(packet::stream_source_t recv_source_id, if (feedback_monitor_ && feedback_monitor_->is_started()) { audio::FeedbackMonitorMetrics metrics; + metrics.jitter = recv_report.jitter; + metrics.niq_latency = recv_report.niq_latency; metrics.e2e_latency = recv_report.e2e_latency; feedback_monitor_->store(metrics);