1use 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#[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 pub fn block_iter(&self) -> impl Iterator<Item = DelaySinceLastReceiverReportBlock> + '_ {
48 DelaySinceLastReceiverReportBlockIter {
49 dlrr: self,
50 data_offset: 4,
51 }
52 }
53
54 pub fn builder() -> DelaySinceLastReceiverReportBuilder {
57 DelaySinceLastReceiverReportBuilder::default()
58 }
59}
60
61#[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 pub fn ssrc(&self) -> u32 {
80 self.ssrc
81 }
82
83 pub fn last_receiver_report(&self) -> u32 {
85 self.last_receiver_report
86 }
87
88 pub fn delay_since_last_receiver_report_timestamp(&self) -> u32 {
90 self.delay_since_last_receiver_report_timestamp
91 }
92
93 pub fn builder() -> DelaySinceLastReceiverReportBlockBuilder {
95 DelaySinceLastReceiverReportBlockBuilder::default()
96 }
97}
98
99#[derive(Debug, Default)]
101pub struct DelaySinceLastReceiverReportBlockBuilder {
102 dlrr: DelaySinceLastReceiverReportBlock,
103}
104
105impl DelaySinceLastReceiverReportBlockBuilder {
106 pub fn ssrc(mut self, ssrc: u32) -> Self {
108 self.dlrr.ssrc = ssrc;
109 self
110 }
111
112 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 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#[derive(Debug, Default)]
162pub struct DelaySinceLastReceiverReportBuilder {
163 blocks: Vec<DelaySinceLastReceiverReportBlockBuilder>,
164}
165
166impl DelaySinceLastReceiverReportBuilder {
167 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}