rtcp_types/xr/
dlrr.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::prelude::*;
4use crate::utils::u32_from_be_bytes;
5use crate::xr::{XrBlockBuilder, XrBlockParser, XrBlockStaticType};
6use crate::{RtcpParseError, RtcpWriteError};
7
8use super::XrBlock;
9
10/// Packet Receipt Times information as specified in RFC 3611
11#[derive(Debug)]
12pub struct DelaySinceLastReceiverReport<'a> {
13    block: XrBlock<'a>,
14}
15
16impl XrBlockStaticType for DelaySinceLastReceiverReport<'_> {
17    const BLOCK_TYPE: u8 = 0x5;
18}
19
20impl<'a> XrBlockParser<'a> for DelaySinceLastReceiverReport<'a> {
21    fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
22        let block = XrBlock::parse(data)?;
23        if data.len() < 16 {
24            return Err(RtcpParseError::Truncated {
25                expected: 16,
26                actual: data.len(),
27            });
28        }
29        let ret = Self { block };
30        if ret.length() % 16 != 0 {
31            return Err(RtcpParseError::Truncated {
32                expected: ret.length() + ret.length() % 16,
33                actual: data.len(),
34            });
35        }
36        Ok(ret)
37    }
38
39    #[inline(always)]
40    fn header_data(&self) -> [u8; 4] {
41        self.block.data[..4].try_into().unwrap()
42    }
43}
44
45impl DelaySinceLastReceiverReport<'_> {
46    /// An iterator over the report blocks [`DelaySinceLastReceiverReport`].
47    pub fn block_iter(&self) -> impl Iterator<Item = DelaySinceLastReceiverReportBlock> + '_ {
48        DelaySinceLastReceiverReportBlockIter {
49            dlrr: self,
50            data_offset: 4,
51        }
52    }
53
54    /// Returns a [`DelaySinceLastReceiverReportBuilder`] for constructing a
55    /// [`DelaySinceLastReceiverReport`] block.
56    pub fn builder() -> DelaySinceLastReceiverReportBuilder {
57        DelaySinceLastReceiverReportBuilder::default()
58    }
59}
60
61/// A report block as stored in a [`DelaySinceLastReceiverReport`]
62#[derive(Debug, Default)]
63pub struct DelaySinceLastReceiverReportBlock {
64    ssrc: u32,
65    last_receiver_report: u32,
66    delay_since_last_receiver_report_timestamp: u32,
67}
68
69impl DelaySinceLastReceiverReportBlock {
70    fn parse(data: &[u8]) -> Self {
71        Self {
72            ssrc: u32_from_be_bytes(&data[..4]),
73            last_receiver_report: u32_from_be_bytes(&data[4..8]),
74            delay_since_last_receiver_report_timestamp: u32_from_be_bytes(&data[8..12]),
75        }
76    }
77
78    /// The SSRC this block refers to
79    pub fn ssrc(&self) -> u32 {
80        self.ssrc
81    }
82
83    /// The NTP 16.16 fixed point time that a receiver report was last received
84    pub fn last_receiver_report(&self) -> u32 {
85        self.last_receiver_report
86    }
87
88    /// 16.16 fixed point duration since the last receiver report was received
89    pub fn delay_since_last_receiver_report_timestamp(&self) -> u32 {
90        self.delay_since_last_receiver_report_timestamp
91    }
92
93    /// Construct a builder for a [`DelaySinceLastReceiverReportBlock`]
94    pub fn builder() -> DelaySinceLastReceiverReportBlockBuilder {
95        DelaySinceLastReceiverReportBlockBuilder::default()
96    }
97}
98
99/// Builder for a [`DelaySinceLastReceiverReportBlock`]
100#[derive(Debug, Default)]
101pub struct DelaySinceLastReceiverReportBlockBuilder {
102    dlrr: DelaySinceLastReceiverReportBlock,
103}
104
105impl DelaySinceLastReceiverReportBlockBuilder {
106    /// The SSRC this block refers to
107    pub fn ssrc(mut self, ssrc: u32) -> Self {
108        self.dlrr.ssrc = ssrc;
109        self
110    }
111
112    /// The NTP 16.16 fixed point time that a receiver report was last received
113    pub fn last_receiver_report(mut self, last_receiver_report: u32) -> Self {
114        self.dlrr.last_receiver_report = last_receiver_report;
115        self
116    }
117
118    /// 16.16 fixed point duration since the last receiver report was received
119    pub fn delay_since_last_receiver_report_timestamp(
120        mut self,
121        delay_since_last_receiver_report_timestamp: u32,
122    ) -> Self {
123        self.dlrr.delay_since_last_receiver_report_timestamp =
124            delay_since_last_receiver_report_timestamp;
125        self
126    }
127
128    fn write_into(&self, buf: &mut [u8]) {
129        buf[..4].copy_from_slice(&self.dlrr.ssrc.to_be_bytes());
130        buf[4..8].copy_from_slice(&self.dlrr.last_receiver_report.to_be_bytes());
131        buf[8..12].copy_from_slice(
132            &self
133                .dlrr
134                .delay_since_last_receiver_report_timestamp
135                .to_be_bytes(),
136        );
137    }
138}
139
140#[derive(Debug)]
141struct DelaySinceLastReceiverReportBlockIter<'a> {
142    dlrr: &'a DelaySinceLastReceiverReport<'a>,
143    data_offset: usize,
144}
145
146impl Iterator for DelaySinceLastReceiverReportBlockIter<'_> {
147    type Item = DelaySinceLastReceiverReportBlock;
148
149    fn next(&mut self) -> Option<Self::Item> {
150        if self.data_offset + 12 > self.dlrr.block.data.len() {
151            return None;
152        }
153        let block =
154            DelaySinceLastReceiverReportBlock::parse(&self.dlrr.block.data[self.data_offset..]);
155        self.data_offset += 12;
156        Some(block)
157    }
158}
159
160/// A builder for a [`DelaySinceLastReceiverReport`]
161#[derive(Debug, Default)]
162pub struct DelaySinceLastReceiverReportBuilder {
163    blocks: Vec<DelaySinceLastReceiverReportBlockBuilder>,
164}
165
166impl DelaySinceLastReceiverReportBuilder {
167    /// Add a report block to this [`DelaySinceLastReceiverReport`]
168    pub fn add_block(mut self, block: DelaySinceLastReceiverReportBlockBuilder) -> Self {
169        self.blocks.push(block);
170        self
171    }
172}
173
174impl XrBlockBuilder<'_> for DelaySinceLastReceiverReportBuilder {
175    fn type_specific_byte(&self) -> u8 {
176        0
177    }
178}
179
180impl RtcpPacketWriter for DelaySinceLastReceiverReportBuilder {
181    fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
182        Ok(4 + self.blocks.len() * 12)
183    }
184
185    fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
186        let mut idx = self.write_header_unchecked(
187            buf,
188            DelaySinceLastReceiverReport::BLOCK_TYPE,
189            (self.blocks.len() * 12 / 4) as u16,
190        );
191        for block in self.blocks.iter() {
192            block.write_into(&mut buf[idx..]);
193            idx += 12;
194        }
195
196        idx
197    }
198
199    fn get_padding(&self) -> Option<u8> {
200        None
201    }
202}
203
204#[cfg(test)]
205mod tests {
206    use super::*;
207
208    #[test]
209    fn dlrr_single_block() {
210        let builder = DelaySinceLastReceiverReport::builder().add_block(
211            DelaySinceLastReceiverReportBlock::builder()
212                .ssrc(0x9876_5432)
213                .last_receiver_report(0x1357_8642)
214                .delay_since_last_receiver_report_timestamp(0x8642_1357),
215        );
216        let len = builder.calculate_size().unwrap();
217        let mut buf = vec![0; len];
218        builder.write_into(&mut buf).unwrap();
219        println!("{buf:x?}");
220
221        let dlrr = DelaySinceLastReceiverReport::parse(&buf).unwrap();
222        let mut block_iter = dlrr.block_iter();
223        let block = block_iter.next().unwrap();
224        assert!(block_iter.next().is_none());
225        assert_eq!(block.ssrc(), 0x9876_5432);
226        assert_eq!(block.last_receiver_report(), 0x1357_8642);
227        assert_eq!(
228            block.delay_since_last_receiver_report_timestamp(),
229            0x8642_1357
230        );
231    }
232}