rtcp_types/xr/
rle.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::prelude::*;
4use crate::{utils::u32_from_be_bytes, RtcpParseError};
5
6use super::{pad_to_4bytes, u16_from_be_bytes, xr_offset_sequence, RtcpPacketWriter, XrBlock};
7
8/// Run-Length-Encoded block (packet loss or duplicate) as specified in RFC 3611
9#[derive(Debug)]
10pub struct Rle<'a> {
11    pub(crate) block: XrBlock<'a>,
12}
13
14impl<'a> Rle<'a> {
15    /// Parse a Rle from a sequence of byte
16    pub fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
17        let block = XrBlock::parse(data)?;
18        if block.length() < 12 {
19            return Err(RtcpParseError::Truncated {
20                expected: 12,
21                actual: block.length(),
22            });
23        }
24        let ret = Self { block };
25        Ok(ret)
26    }
27
28    /// The amount of thinning applied to the sequence number space. Every 2^thinning sequence
29    /// number has been reported
30    pub fn thinning(&self) -> u8 {
31        self.block.data[1] & 0x0f
32    }
33
34    /// The SSRC of the media being reported on
35    pub fn media_ssrc(&self) -> u32 {
36        u32_from_be_bytes(&self.block.data[4..8])
37    }
38
39    /// This is the (inclusive) start of the sequence number range being reported in this Rle packet.
40    /// This start value is included in the range.
41    pub fn begin(&self) -> u16 {
42        u16_from_be_bytes(&self.block.data[8..10])
43    }
44
45    /// This is the (exclusive) end of the sequence number range being reported in this Rle packet.
46    /// This end value is not included in the range.
47    pub fn end(&self) -> u16 {
48        u16_from_be_bytes(&self.block.data[10..12])
49    }
50
51    /// An iterator over the sequence numbers in this [`Rle`]
52    pub fn sequence_iter(&self) -> impl Iterator<Item = u16> + '_ {
53        RleSequenceIter {
54            rle: self,
55            block_iter: RleBlockIter {
56                rle: self,
57                block_offset: 12,
58            },
59            chunk_iter: None,
60            seq_offset: self.begin(),
61        }
62    }
63
64    /// An iterator over the chunks in this [`Rle`]
65    pub fn chunk_iter(&self) -> impl Iterator<Item = RleChunk> + '_ {
66        RleBlockIter {
67            rle: self,
68            block_offset: 12,
69        }
70    }
71
72    /// Returns a new [`RleBuilder`] for constructing a [`Rle`] block.
73    pub fn builder() -> RleBuilder {
74        RleBuilder::default()
75    }
76}
77
78#[derive(Debug)]
79struct RleBlockIter<'a> {
80    rle: &'a Rle<'a>,
81    // which chunk we are looking at
82    block_offset: usize,
83}
84
85impl Iterator for RleBlockIter<'_> {
86    type Item = RleChunk;
87
88    fn next(&mut self) -> Option<Self::Item> {
89        if self.block_offset + 2 >= self.rle.block.length() {
90            return None;
91        }
92        let chunk = RleChunk::parse(&self.rle.block.data[self.block_offset..self.block_offset + 2]);
93        self.block_offset += 2;
94        Some(chunk)
95    }
96}
97
98pub struct RleSequenceIter<'a> {
99    rle: &'a Rle<'a>,
100    block_iter: RleBlockIter<'a>,
101    chunk_iter: Option<RleChunkIter>,
102    seq_offset: u16,
103}
104
105impl Iterator for RleSequenceIter<'_> {
106    type Item = u16;
107
108    fn next(&mut self) -> Option<Self::Item> {
109        loop {
110            if let Some(it) = self.chunk_iter.as_mut() {
111                let ret = it.next();
112                if ret.is_none() {
113                    let len = it.length() as u16;
114                    let diff = 2u16.pow(self.rle.thinning() as u32).wrapping_mul(len);
115                    self.seq_offset = self.seq_offset.wrapping_add(diff);
116                    self.chunk_iter = None;
117                } else {
118                    return ret.and_then(|seq| {
119                        xr_offset_sequence(
120                            seq,
121                            self.seq_offset,
122                            self.rle.end(),
123                            self.rle.thinning(),
124                        )
125                    });
126                }
127            }
128            let chunk = self.block_iter.next()?;
129            self.chunk_iter = Some(chunk.iter());
130        }
131    }
132}
133
134/// The various options for what a RLE chunk can be.
135#[derive(Debug, Copy, Clone, PartialEq, Eq)]
136pub enum RleChunk {
137    /// Run length where 1s are set. The least significant 14 bits contain the length of the run.
138    RunLength(u16),
139    /// Run length where 0s are set. The least significant 14 bits contain the length of the run.
140    SkipLength(u16),
141    /// The least significant 15 bits contain a bit mask of values. The value is read from most
142    /// significat to the least significant bit.
143    BitVector(u16),
144    /// Null value.  Should be skipped in most scenarios.
145    Null,
146}
147
148impl RleChunk {
149    fn parse(data: &[u8]) -> Self {
150        let value = u16_from_be_bytes(data);
151        if value == 0 {
152            return Self::Null;
153        }
154        if (value & 0x8000) == 0x8000 {
155            Self::BitVector(value & !0x8000)
156        } else if (value & 0x4000) == 0x4000 {
157            Self::RunLength(value & !0xc000)
158        } else {
159            Self::SkipLength(value & !0xc000)
160        }
161    }
162
163    fn length(&self) -> usize {
164        match self {
165            Self::Null => 0,
166            Self::BitVector(_) => 15,
167            Self::SkipLength(rle) | Self::RunLength(rle) => (rle & !0xc000) as usize,
168        }
169    }
170
171    fn iter(&self) -> RleChunkIter {
172        RleChunkIter {
173            chunk: *self,
174            chunk_offset: 0,
175        }
176    }
177
178    fn write_into(&self, buf: &mut [u8]) {
179        match self {
180            Self::Null => {
181                buf[0] = 0x0;
182                buf[1] = 0x0;
183            }
184            Self::RunLength(rle) => {
185                buf[..2].copy_from_slice(&((rle & !0xc000) | 0x4000).to_be_bytes())
186            }
187            Self::SkipLength(rle) => buf[..2].copy_from_slice(&(rle & !0xc000).to_be_bytes()),
188            Self::BitVector(vector) => buf[..2].copy_from_slice(&(vector | 0x8000).to_be_bytes()),
189        }
190    }
191}
192
193#[derive(Debug)]
194struct RleChunkIter {
195    chunk: RleChunk,
196    chunk_offset: u16,
197}
198
199impl Iterator for RleChunkIter {
200    type Item = u16;
201
202    fn next(&mut self) -> Option<Self::Item> {
203        match self.chunk {
204            RleChunk::Null | RleChunk::SkipLength(_) => None,
205            RleChunk::BitVector(vector) => {
206                while self.chunk_offset < 15 {
207                    let value = (vector & !0x8000) >> (14 - self.chunk_offset) & 0x1;
208                    if value > 0 {
209                        break;
210                    }
211                    self.chunk_offset += 1
212                }
213                if self.chunk_offset >= 15 {
214                    None
215                } else {
216                    let ret = self.chunk_offset;
217                    self.chunk_offset += 1;
218                    Some(ret)
219                }
220            }
221            RleChunk::RunLength(rlen) => {
222                let rlen = rlen & !0xc000;
223                if self.chunk_offset < rlen {
224                    let ret = self.chunk_offset;
225                    self.chunk_offset += 1;
226                    Some(ret)
227                } else {
228                    None
229                }
230            }
231        }
232    }
233}
234
235impl RleChunkIter {
236    fn length(&self) -> usize {
237        self.chunk.length()
238    }
239}
240
241#[derive(Debug, Default)]
242pub struct RleBuilder {
243    block_type: u8,
244    media_ssrc: u32,
245    begin: u16,
246    end: u16,
247    chunks: Vec<RleChunk>,
248    thinning: u8,
249}
250
251impl RleBuilder {
252    pub fn block_type(mut self, block_type: u8) -> Self {
253        self.block_type = block_type;
254        self
255    }
256
257    pub fn ssrc(mut self, ssrc: u32) -> Self {
258        self.media_ssrc = ssrc;
259        self
260    }
261
262    pub fn begin(mut self, begin: u16) -> Self {
263        self.begin = begin;
264        self
265    }
266
267    pub fn end(mut self, end: u16) -> Self {
268        self.end = end;
269        self
270    }
271
272    pub fn thinning(mut self, thinning: u8) -> Self {
273        self.thinning = thinning;
274        self
275    }
276
277    pub fn add_chunk(mut self, chunk: RleChunk) -> Self {
278        self.chunks.push(chunk);
279        self
280    }
281}
282
283impl XrBlockBuilder<'_> for RleBuilder {
284    fn type_specific_byte(&self) -> u8 {
285        self.thinning & 0xf
286    }
287}
288
289impl RtcpPacketWriter for RleBuilder {
290    fn calculate_size(&self) -> Result<usize, crate::RtcpWriteError> {
291        Ok(12 + pad_to_4bytes(self.chunks.len() * 2))
292    }
293
294    fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
295        self.write_header_unchecked(
296            buf,
297            self.block_type,
298            (pad_to_4bytes(self.chunks.len() * 2) / 4) as u16 + 2,
299        );
300        buf[4..8].copy_from_slice(&self.media_ssrc.to_be_bytes());
301        buf[8..10].copy_from_slice(&self.begin.to_be_bytes());
302        buf[10..12].copy_from_slice(&self.end.to_be_bytes());
303        let mut idx = 12;
304        for chunk in self.chunks.iter() {
305            chunk.write_into(&mut buf[idx..idx + 2]);
306            idx += 2;
307        }
308        if idx % 4 != 0 {
309            RleChunk::Null.write_into(&mut buf[idx..idx + 2]);
310            idx += 2;
311        }
312        idx
313    }
314
315    fn get_padding(&self) -> Option<u8> {
316        None
317    }
318}
319
320#[cfg(test)]
321mod tests {
322    use super::*;
323
324    #[test]
325    fn bit_chunk_iter() {
326        let chunk = RleChunk::BitVector(0b1011_0100_0111_1001);
327        assert_eq!(chunk.length(), 15);
328        let sequences = chunk.iter().collect::<Vec<_>>();
329        let expected = vec![1, 2, 4, 8, 9, 10, 11, 14];
330        assert_eq!(sequences, expected);
331    }
332
333    #[test]
334    fn bit_chunk_iter_single_value() {
335        for i in 0..14 {
336            let chunk = RleChunk::BitVector(0x8000 | (0x1 << i));
337            assert_eq!(chunk.length(), 15);
338            let sequences = chunk.iter().collect::<Vec<_>>();
339            let expected = vec![14 - i];
340            assert_eq!(sequences, expected);
341        }
342    }
343
344    #[test]
345    fn null_chunk_iter() {
346        let chunk = RleChunk::Null;
347        assert_eq!(chunk.length(), 0);
348        assert_eq!(chunk.iter().next(), None);
349    }
350
351    #[test]
352    fn skip_chunk_iter() {
353        let chunk = RleChunk::SkipLength(29);
354        assert_eq!(chunk.length(), 29);
355        assert_eq!(chunk.iter().next(), None);
356    }
357
358    #[test]
359    fn run_chunk_iter() {
360        let chunk = RleChunk::RunLength(18);
361        assert_eq!(chunk.length(), 18);
362        let expected = (0..18).collect::<Vec<_>>();
363        let sequences = chunk.iter().collect::<Vec<_>>();
364        assert_eq!(sequences, expected);
365    }
366
367    #[test]
368    fn rle_builder_vector_larger_than_sequence_range() {
369        let builder = Rle::builder()
370            .block_type(0x48)
371            .ssrc(0x1357_9864)
372            .begin(u16::MAX - 3)
373            .end(4)
374            .thinning(0)
375            .add_chunk(RleChunk::BitVector(0b0111_1111_1111_1111));
376        let len = builder.calculate_size().unwrap();
377        let mut buf = vec![0; len];
378        builder.write_into_unchecked(&mut buf);
379        println!("{buf:x?}");
380
381        let rle = Rle::parse(&buf).unwrap();
382        assert_eq!(rle.media_ssrc(), 0x1357_9864);
383        assert_eq!(rle.thinning(), 0);
384        assert_eq!(rle.begin(), u16::MAX - 3);
385        assert_eq!(rle.end(), 4);
386        let expected = (u16::MAX - 3..=u16::MAX).chain(0..4).collect::<Vec<_>>();
387        let sequence = rle.sequence_iter().collect::<Vec<_>>();
388        assert_eq!(sequence, expected);
389    }
390}