rtp/extension/abs_send_time_extension/
mod.rs

1#[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/// AbsSendTimeExtension is a extension payload format in
14/// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
15#[derive(PartialEq, Eq, Debug, Default, Copy, Clone)]
16pub struct AbsSendTimeExtension {
17    pub timestamp: u64,
18}
19
20impl Unmarshal for AbsSendTimeExtension {
21    /// Unmarshal parses the passed byte slice and stores the result in the members.
22    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    /// MarshalSize returns the size of the AbsSendTimeExtension once marshaled.
42    fn marshal_size(&self) -> usize {
43        ABS_SEND_TIME_EXTENSION_SIZE
44    }
45}
46
47impl Marshal for AbsSendTimeExtension {
48    /// MarshalTo serializes the members to buffer.
49    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    /// Estimate absolute send time according to the receive time.
64    /// Note that if the transmission delay is larger than 64 seconds, estimated time will be wrong.
65    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            // Receive time must be always later than send time
70            ntp -= 0x1000000 << 14;
71        }
72
73        ntp2unix(ntp)
74    }
75
76    /// NewAbsSendTimeExtension makes new AbsSendTimeExtension from time.Time.
77    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; //offset in seconds between unix epoch and ntp epoch
91    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}