rtc_rtcp/extended_report/
rle.rs1use super::*;
2
3const RLE_REPORT_BLOCK_MIN_LENGTH: u16 = 8;
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub enum ChunkType {
8 RunLength = 0,
9 BitVector = 1,
10 TerminatingNull = 2,
11}
12
13#[derive(Debug, Default, PartialEq, Eq, Clone)]
40pub struct Chunk(pub u16);
41
42impl fmt::Display for Chunk {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self.chunk_type() {
45 ChunkType::RunLength => {
46 let run_type = self.run_type().unwrap_or(0);
47 write!(f, "[RunLength type={}, length={}]", run_type, self.value())
48 }
49 ChunkType::BitVector => write!(f, "[BitVector {:#b}", self.value()),
50 ChunkType::TerminatingNull => write!(f, "[TerminatingNull]"),
51 }
52 }
53}
54impl Chunk {
55 pub fn chunk_type(&self) -> ChunkType {
57 if self.0 == 0 {
58 ChunkType::TerminatingNull
59 } else if (self.0 >> 15) == 0 {
60 ChunkType::RunLength
61 } else {
62 ChunkType::BitVector
63 }
64 }
65
66 pub fn run_type(&self) -> Result<u8> {
69 if self.chunk_type() != ChunkType::RunLength {
70 Err(Error::WrongChunkType)
71 } else {
72 Ok((self.0 >> 14) as u8 & 0x01)
73 }
74 }
75
76 pub fn value(&self) -> u16 {
78 match self.chunk_type() {
79 ChunkType::RunLength => self.0 & 0x3FFF,
80 ChunkType::BitVector => self.0 & 0x7FFF,
81 ChunkType::TerminatingNull => 0,
82 }
83 }
84}
85
86#[derive(Debug, Default, PartialEq, Eq, Clone)]
106pub struct RLEReportBlock {
107 pub is_loss_rle: bool,
109 pub t: u8,
110
111 pub ssrc: u32,
113 pub begin_seq: u16,
114 pub end_seq: u16,
115 pub chunks: Vec<Chunk>,
116}
117
118pub type LossRLEReportBlock = RLEReportBlock;
122
123pub type DuplicateRLEReportBlock = RLEReportBlock;
127
128impl RLEReportBlock {
129 pub fn xr_header(&self) -> XRHeader {
130 XRHeader {
131 block_type: if self.is_loss_rle {
132 BlockType::LossRLE
133 } else {
134 BlockType::DuplicateRLE
135 },
136 type_specific: self.t & 0x0F,
137 block_length: (self.raw_size() / 4 - 1) as u16,
138 }
139 }
140}
141
142impl fmt::Display for RLEReportBlock {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "{self:?}")
145 }
146}
147
148impl Packet for RLEReportBlock {
149 fn header(&self) -> Header {
150 Header::default()
151 }
152
153 fn destination_ssrc(&self) -> Vec<u32> {
155 vec![self.ssrc]
156 }
157
158 fn raw_size(&self) -> usize {
159 XR_HEADER_LENGTH + RLE_REPORT_BLOCK_MIN_LENGTH as usize + self.chunks.len() * 2
160 }
161
162 fn as_any(&self) -> &dyn Any {
163 self
164 }
165 fn equal(&self, other: &dyn Packet) -> bool {
166 other.as_any().downcast_ref::<RLEReportBlock>() == Some(self)
167 }
168 fn cloned(&self) -> Box<dyn Packet> {
169 Box::new(self.clone())
170 }
171}
172
173impl MarshalSize for RLEReportBlock {
174 fn marshal_size(&self) -> usize {
175 self.raw_size()
176 }
177}
178
179impl Marshal for RLEReportBlock {
180 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
182 if buf.remaining_mut() < self.marshal_size() {
183 return Err(Error::BufferTooShort);
184 }
185
186 let h = self.xr_header();
187 let n = h.marshal_to(buf)?;
188 buf = &mut buf[n..];
189
190 buf.put_u32(self.ssrc);
191 buf.put_u16(self.begin_seq);
192 buf.put_u16(self.end_seq);
193 for chunk in &self.chunks {
194 buf.put_u16(chunk.0);
195 }
196
197 Ok(self.marshal_size())
198 }
199}
200
201impl Unmarshal for RLEReportBlock {
202 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
204 where
205 Self: Sized,
206 B: Buf,
207 {
208 if raw_packet.remaining() < XR_HEADER_LENGTH {
209 return Err(Error::PacketTooShort);
210 }
211
212 let xr_header = XRHeader::unmarshal(raw_packet)?;
213 let block_length = match xr_header.block_length.checked_mul(4) {
214 Some(length) => length,
215 None => return Err(Error::InvalidBlockSize),
216 };
217 if block_length < RLE_REPORT_BLOCK_MIN_LENGTH
218 || !(block_length - RLE_REPORT_BLOCK_MIN_LENGTH).is_multiple_of(2)
219 || raw_packet.remaining() < block_length as usize
220 {
221 return Err(Error::PacketTooShort);
222 }
223
224 let is_loss_rle = xr_header.block_type == BlockType::LossRLE;
225 let t = xr_header.type_specific & 0x0F;
226
227 let ssrc = raw_packet.get_u32();
228 let begin_seq = raw_packet.get_u16();
229 let end_seq = raw_packet.get_u16();
230
231 let remaining = block_length - RLE_REPORT_BLOCK_MIN_LENGTH;
232 let mut chunks = vec![];
233 for _ in 0..remaining / 2 {
234 chunks.push(Chunk(raw_packet.get_u16()));
235 }
236
237 Ok(RLEReportBlock {
238 is_loss_rle,
239 t,
240 ssrc,
241 begin_seq,
242 end_seq,
243 chunks,
244 })
245 }
246}