use crate::decode::rtcp::{SrReport, ntp_to_seconds};
pub fn rtt_from_rr(arrival_ntp_secs: f64, block: &crate::decode::rtcp::ReportBlock) -> Option<f64> {
if block.lsr == 0 {
return None;
}
let arrival_mid32 = ((arrival_ntp_secs * 65536.0) as u64 & 0xFFFF_FFFF) as f64;
let lsr = block.lsr as f64;
let dlsr = block.dlsr as f64;
let mut diff = arrival_mid32 - lsr - dlsr;
if diff < 0.0 {
diff += 4_294_967_296.0; }
if !(0.0..=60.0 * 65536.0).contains(&diff) {
return None;
}
Some(diff / 65536.0 * 1000.0)
}
pub fn oneway_from_sr(arrival_ntp_secs: f64, sr: &SrReport) -> Option<f64> {
let sent = ntp_to_seconds(sr.sender.ntp_secs, sr.sender.ntp_frac);
let mut d = arrival_ntp_secs - sent;
if d < 0.0 {
d += 4_294_967_296.0; }
if !(0.0..=60.0).contains(&d) {
return None;
}
Some(d * 1000.0)
}
pub fn unix_us_to_ntp_secs(ts_us: u64) -> f64 {
const NTP_UNIX_OFFSET: u64 = 2_208_988_800; let secs = (ts_us / 1_000_000) as f64 + NTP_UNIX_OFFSET as f64;
let frac = (ts_us % 1_000_000) as f64 / 1_000_000.0;
secs + frac
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rtt_round_trip_sane() {
let t0 = unix_us_to_ntp_secs(1_000_000_000_000_000); let lsr = ((t0 * 65536.0).round() as u64 & 0xFFFF_FFFF) as u32;
let block = crate::decode::rtcp::ReportBlock {
ssrc: 1,
fraction_lost: 0,
cumulative_lost: 0,
highest_seq: 0,
jitter: 0,
lsr,
dlsr: (0.5_f64 * 65536.0) as u32,
};
let arrival = t0 + 0.6;
let rtt = rtt_from_rr(arrival, &block).unwrap();
assert!(rtt > 50.0 && rtt < 200.0, "rtt={rtt}");
}
}