rtcp_types/xr/
duplicate_rle.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::prelude::*;
4use crate::xr::rle::{Rle, RleBuilder, RleChunk};
5use crate::xr::{XrBlockBuilder, XrBlockParser, XrBlockStaticType};
6use crate::{RtcpParseError, RtcpWriteError};
7
8/// Run-Length-Encoded packet duplicate information as specified in RFC 3611
9#[derive(Debug)]
10pub struct DuplicateRle<'a> {
11    rle: Rle<'a>,
12}
13
14impl XrBlockStaticType for DuplicateRle<'_> {
15    const BLOCK_TYPE: u8 = 0x2;
16}
17
18impl<'a> XrBlockParser<'a> for DuplicateRle<'a> {
19    fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
20        let rle = Rle::parse(data)?;
21        let ret = Self { rle };
22        Ok(ret)
23    }
24
25    #[inline(always)]
26    fn header_data(&self) -> [u8; 4] {
27        self.rle.block.header_data()
28    }
29}
30
31impl DuplicateRle<'_> {
32    /// The amount of thinning applied to the sequence number space. Every 2^thinning sequence
33    /// number has been reported
34    pub fn thinning(&self) -> u8 {
35        self.rle.thinning()
36    }
37
38    /// The SSRC of the media being reported on
39    pub fn media_ssrc(&self) -> u32 {
40        self.rle.media_ssrc()
41    }
42
43    /// This is the (inclusive) start of the sequence number range being reported in this Rle block.
44    /// This start value is included in the range.
45    pub fn begin(&self) -> u16 {
46        self.rle.begin()
47    }
48
49    /// This is the (exclusive) end of the sequence number range being reported in this Rle block.
50    /// This end value is not included in the range.
51    pub fn end(&self) -> u16 {
52        self.rle.end()
53    }
54
55    /// An iterator over the sequence numbers in this [`DuplicateRle`].
56    pub fn sequence_iter(&self) -> impl Iterator<Item = u16> + '_ {
57        self.rle.sequence_iter()
58    }
59
60    /// An iterator over the chunks in this [`DuplicateRle`].
61    ///
62    /// This returns chunks as they are stored without any sequence number translation applied.
63    /// i.e. each chunk starts from a sequence number of 0.
64    pub fn chunk_iter(&self) -> impl Iterator<Item = RleChunk> + '_ {
65        self.rle.chunk_iter()
66    }
67
68    /// Returns a [`DuplicateRleBuilder`] for constructing a [`DuplicateRle`] block.
69    pub fn builder() -> DuplicateRleBuilder {
70        let mut builder = DuplicateRleBuilder {
71            rle: Rle::builder(),
72        };
73        builder.rle = builder.rle.block_type(Self::BLOCK_TYPE);
74        builder
75    }
76}
77
78/// Builder for a [`DuplicateRle`]
79#[derive(Debug, Default)]
80pub struct DuplicateRleBuilder {
81    rle: RleBuilder,
82}
83
84impl DuplicateRleBuilder {
85    /// Set the SSRC the [`DuplicateRle`] refers to.
86    pub fn ssrc(mut self, ssrc: u32) -> Self {
87        self.rle = self.rle.ssrc(ssrc);
88        self
89    }
90
91    /// Set the start of the sequence number range.
92    pub fn begin(mut self, begin: u16) -> Self {
93        self.rle = self.rle.begin(begin);
94        self
95    }
96
97    /// Set the end of the sequence number range.
98    pub fn end(mut self, end: u16) -> Self {
99        self.rle = self.rle.end(end);
100        self
101    }
102
103    /// Set the thinning value for the [`DuplicateRle`].
104    ///
105    /// Thinning signals that ever this block reports on every 2^thinning sequence number.
106    pub fn thinning(mut self, thinning: u8) -> Self {
107        assert!(thinning <= 0xf);
108        self.rle = self.rle.thinning(thinning);
109        self
110    }
111
112    /// Add a chunk for this [`DuplicateRle`]
113    pub fn add_chunk(mut self, chunk: RleChunk) -> Self {
114        self.rle = self.rle.add_chunk(chunk);
115        self
116    }
117}
118
119impl XrBlockBuilder<'_> for DuplicateRleBuilder {
120    fn type_specific_byte(&self) -> u8 {
121        self.rle.type_specific_byte()
122    }
123}
124
125impl RtcpPacketWriter for DuplicateRleBuilder {
126    fn calculate_size(&self) -> Result<usize, RtcpWriteError> {
127        self.rle.calculate_size()
128    }
129
130    fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
131        self.rle.write_into_unchecked(buf)
132    }
133
134    fn get_padding(&self) -> Option<u8> {
135        None
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn duplicate_rle_builder_wraparound() {
145        let builder = DuplicateRle::builder()
146            .ssrc(0x1357_9864)
147            .begin(u16::MAX - 51)
148            .end(50)
149            .thinning(1)
150            .add_chunk(RleChunk::RunLength(51));
151        let len = builder.calculate_size().unwrap();
152        let mut buf = vec![0; len];
153        builder.write_into_unchecked(&mut buf);
154        println!("{buf:x?}");
155
156        let rle = DuplicateRle::parse(&buf).unwrap();
157        assert_eq!(rle.media_ssrc(), 0x1357_9864);
158        assert_eq!(rle.thinning(), 1);
159        assert_eq!(rle.begin(), u16::MAX - 51);
160        assert_eq!(rle.end(), 50);
161        let expected = (u16::MAX - 51..u16::MAX)
162            .chain(0..50)
163            .filter(|x| x % 2 == 0)
164            .collect::<Vec<_>>();
165        let sequence = rle.sequence_iter().collect::<Vec<_>>();
166        assert_eq!(sequence, expected);
167    }
168}