rtp/extension/abs_send_time_extension/
mod.rs1#[cfg(test)]
2mod abs_send_time_extension_test;
3
4use std::time::{Duration, SystemTime, UNIX_EPOCH};
5
6use bytes::{Buf, BufMut};
7use util::marshal::{Marshal, MarshalSize, Unmarshal};
8
9use crate::error::Error;
10
11pub const ABS_SEND_TIME_EXTENSION_SIZE: usize = 3;
12
13#[derive(PartialEq, Eq, Debug, Default, Copy, Clone)]
16pub struct AbsSendTimeExtension {
17 pub timestamp: u64,
18}
19
20impl Unmarshal for AbsSendTimeExtension {
21 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error>
23 where
24 Self: Sized,
25 B: Buf,
26 {
27 if raw_packet.remaining() < ABS_SEND_TIME_EXTENSION_SIZE {
28 return Err(Error::ErrBufferTooSmall.into());
29 }
30
31 let b0 = raw_packet.get_u8();
32 let b1 = raw_packet.get_u8();
33 let b2 = raw_packet.get_u8();
34 let timestamp = (b0 as u64) << 16 | (b1 as u64) << 8 | b2 as u64;
35
36 Ok(AbsSendTimeExtension { timestamp })
37 }
38}
39
40impl MarshalSize for AbsSendTimeExtension {
41 fn marshal_size(&self) -> usize {
43 ABS_SEND_TIME_EXTENSION_SIZE
44 }
45}
46
47impl Marshal for AbsSendTimeExtension {
48 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> {
50 if buf.remaining_mut() < ABS_SEND_TIME_EXTENSION_SIZE {
51 return Err(Error::ErrBufferTooSmall.into());
52 }
53
54 buf.put_u8(((self.timestamp & 0xFF0000) >> 16) as u8);
55 buf.put_u8(((self.timestamp & 0xFF00) >> 8) as u8);
56 buf.put_u8((self.timestamp & 0xFF) as u8);
57
58 Ok(ABS_SEND_TIME_EXTENSION_SIZE)
59 }
60}
61
62impl AbsSendTimeExtension {
63 pub fn estimate(&self, receive: SystemTime) -> SystemTime {
66 let receive_ntp = unix2ntp(receive);
67 let mut ntp = receive_ntp & 0xFFFFFFC000000000 | (self.timestamp & 0xFFFFFF) << 14;
68 if receive_ntp < ntp {
69 ntp -= 0x1000000 << 14;
71 }
72
73 ntp2unix(ntp)
74 }
75
76 pub fn new(send_time: SystemTime) -> Self {
78 AbsSendTimeExtension {
79 timestamp: unix2ntp(send_time) >> 14,
80 }
81 }
82}
83
84pub fn unix2ntp(st: SystemTime) -> u64 {
85 let u = st
86 .duration_since(UNIX_EPOCH)
87 .unwrap_or_else(|_| Duration::from_secs(0))
88 .as_nanos() as u64;
89 let mut s = u / 1_000_000_000;
90 s += 0x83AA7E80; let mut f = u % 1_000_000_000;
92 f <<= 32;
93 f /= 1_000_000_000;
94 s <<= 32;
95
96 s | f
97}
98
99pub fn ntp2unix(t: u64) -> SystemTime {
100 let mut s = t >> 32;
101 let mut f = t & 0xFFFFFFFF;
102 f *= 1_000_000_000;
103 f >>= 32;
104 s -= 0x83AA7E80;
105 let u = s * 1_000_000_000 + f;
106
107 UNIX_EPOCH
108 .checked_add(Duration::new(u / 1_000_000_000, (u % 1_000_000_000) as u32))
109 .unwrap_or(UNIX_EPOCH)
110}