1use anyhow::{anyhow, bail, Context, Result};
2use bit_cursor::{
3 bit_read_exts::BitReadExts,
4 byte_order::NetworkOrder,
5 nsw_types::{
6 num_traits::{ConstOne, ConstZero},
7 *,
8 },
9};
10
11use crate::{util::consume_padding, PacketBuffer};
12
13use super::{rtcp_fb_header::RtcpFbHeader, rtcp_header::RtcpHeader};
14
15const U2_TWO: u2 = u2::new(2);
16
17#[derive(Debug)]
52pub struct RtcpFbTccPacket {
53 pub header: RtcpHeader,
54 pub fb_header: RtcpFbHeader,
55 pub packet_reports: Vec<PacketReport>,
56 pub reference_time: u24,
57 pub feedback_packet_count: u8,
58}
59
60impl RtcpFbTccPacket {
61 pub const FMT: u5 = u5::new(15);
62}
63
64pub fn read_rtcp_fb_tcc<B: PacketBuffer>(
65 buf: &mut B,
66 header: RtcpHeader,
67 fb_header: RtcpFbHeader,
68) -> Result<RtcpFbTccPacket> {
69 let (packet_reports, reference_time, feedback_packet_count) = read_rtcp_fb_tcc_data(buf)?;
70 Ok(RtcpFbTccPacket {
71 header,
72 fb_header,
73 packet_reports,
74 reference_time,
75 feedback_packet_count,
76 })
77}
78
79fn read_rtcp_fb_tcc_data<B: PacketBuffer>(buf: &mut B) -> Result<(Vec<PacketReport>, u24, u8)> {
80 let base_seq_num = buf.read_u16::<NetworkOrder>().context("base seq num")?;
81 let packet_status_count = buf
82 .read_u16::<NetworkOrder>()
83 .context("packet status count")?;
84 let reference_time = buf.read_u24::<NetworkOrder>().context("reference time")?;
85 let feedback_packet_count = buf.read_u8().context("feedback packet count")?;
86
87 let mut num_status_remaining = packet_status_count;
88
89 let mut chunks: Vec<SomePacketStatusChunk> = Vec::new();
90 while num_status_remaining > 0 {
91 let chunk = read_some_packet_status_chunk(buf, num_status_remaining as usize)
92 .context("packet status chunk")?;
93 num_status_remaining -= chunk.num_symbols();
94 chunks.push(chunk);
95 }
96 let mut curr_seq_num = base_seq_num;
97 let mut packet_reports: Vec<PacketReport> = Vec::new();
98 for chunk in chunks {
99 for status_symbol in chunk {
100 match status_symbol.delta_size_bytes() {
101 0 => packet_reports.push(PacketReport::UnreceivedPacket {
102 seq_num: curr_seq_num,
103 }),
104 1 => {
105 let delta_ticks = buf
106 .read_u8()
107 .with_context(|| format!("delta ticks for packet {curr_seq_num}"))?;
108 packet_reports.push(PacketReport::ReceivedPacketSmallDelta {
109 seq_num: curr_seq_num,
110 delta_ticks,
111 });
112 }
113 2 => {
114 let delta_ticks = buf
115 .read_u16::<NetworkOrder>()
116 .with_context(|| format!("delta ticks for packet {curr_seq_num}"))?
117 as i16;
118 packet_reports.push(PacketReport::ReceivedPacketLargeOrNegativeDelta {
119 seq_num: curr_seq_num,
120 delta_ticks,
121 });
122 }
123 delta_size_bytes => bail!("Invalid delta size: {delta_size_bytes} bytes"),
124 }
125 curr_seq_num = curr_seq_num.wrapping_add(1);
126 }
127 }
128 consume_padding(buf);
129 Ok((packet_reports, reference_time, feedback_packet_count))
130}
131
132#[derive(Debug, PartialEq)]
133pub enum PacketReport {
134 UnreceivedPacket { seq_num: u16 },
135 ReceivedPacketSmallDelta { seq_num: u16, delta_ticks: u8 },
136 ReceivedPacketLargeOrNegativeDelta { seq_num: u16, delta_ticks: i16 },
137}
138
139#[derive(Copy, Clone, Debug, PartialEq, Eq)]
140pub enum PacketStatusSymbol {
141 NotReceived = 0,
142 ReceivedSmallDelta = 1,
143 ReceivedLargeOrNegativeDelta = 2,
144}
145
146impl PacketStatusSymbol {
147 fn delta_size_bytes(&self) -> usize {
148 match self {
149 PacketStatusSymbol::NotReceived => 0,
150 PacketStatusSymbol::ReceivedSmallDelta => 1,
151 PacketStatusSymbol::ReceivedLargeOrNegativeDelta => 2,
152 }
153 }
154}
155
156impl From<u1> for PacketStatusSymbol {
157 fn from(value: u1) -> Self {
158 match value {
159 u1::ZERO => PacketStatusSymbol::NotReceived,
160 u1::ONE => PacketStatusSymbol::ReceivedSmallDelta,
161 _ => unreachable!(),
162 }
163 }
164}
165
166impl TryFrom<u2> for PacketStatusSymbol {
167 type Error = anyhow::Error;
168
169 fn try_from(value: u2) -> std::prelude::v1::Result<Self, Self::Error> {
170 match value {
171 u2::ZERO => Ok(PacketStatusSymbol::NotReceived),
172 u2::ONE => Ok(PacketStatusSymbol::ReceivedSmallDelta),
173 U2_TWO => Ok(PacketStatusSymbol::ReceivedLargeOrNegativeDelta),
174 pss => Err(anyhow!("Invalid 2 bit packet status symbol: {pss}")),
175 }
176 }
177}
178
179#[derive(Debug, Clone, PartialEq)]
203pub struct StatusVectorChunk(Vec<PacketStatusSymbol>);
204
205impl IntoIterator for StatusVectorChunk {
206 type Item = PacketStatusSymbol;
207
208 type IntoIter = <Vec<PacketStatusSymbol> as IntoIterator>::IntoIter;
209
210 fn into_iter(self) -> Self::IntoIter {
211 self.0.into_iter()
212 }
213}
214
215pub fn read_status_vector_chunk<B: PacketBuffer>(
218 buf: &mut B,
219 max_symbol_count: usize,
220) -> Result<StatusVectorChunk> {
221 let symbol_size = buf.read_u1().context("symbol size")?;
222 let mut packet_status_symbols = match symbol_size {
223 u1::ZERO => {
224 (0..14)
226 .map(|i| {
227 buf.read_u1()
228 .with_context(|| format!("packet status symbol {i}"))
229 .map(|v| v.into())
230 })
231 .collect::<Result<Vec<PacketStatusSymbol>>>()
232 .context("1 bit packet status symbols")
233 }
234 u1::ONE => {
235 (0..7)
237 .map(|i| {
238 buf.read_u2()
239 .with_context(|| format!("packet status symbol {i}"))?
240 .try_into()
241 .context("converting u2 to packet status symbol")
242 })
243 .collect::<Result<Vec<PacketStatusSymbol>>>()
244 .context("2 bit packet status symbols")
245 }
246 _ => unreachable!("u1 can only be 0 or 1"),
247 }?;
248
249 packet_status_symbols.truncate(max_symbol_count);
253
254 Ok(StatusVectorChunk(packet_status_symbols))
255}
256
257#[derive(Debug, Clone, PartialEq, Eq)]
274pub struct RunLengthEncodingChunk {
275 pub symbol: PacketStatusSymbol,
276 pub run_length: u13,
277}
278
279pub struct RunLengthEncodingIterator {
280 symbol: PacketStatusSymbol,
281 curr_idx: u32,
282 length: u32,
283}
284
285impl Iterator for RunLengthEncodingIterator {
286 type Item = PacketStatusSymbol;
287
288 fn next(&mut self) -> Option<Self::Item> {
289 if self.curr_idx < self.length {
290 self.curr_idx += 1;
291 Some(self.symbol)
292 } else {
293 None
294 }
295 }
296}
297
298impl IntoIterator for RunLengthEncodingChunk {
299 type Item = PacketStatusSymbol;
300
301 type IntoIter = RunLengthEncodingIterator;
302
303 fn into_iter(self) -> Self::IntoIter {
304 RunLengthEncodingIterator {
305 symbol: self.symbol,
306 curr_idx: 0,
307 length: self.run_length.into(),
308 }
309 }
310}
311
312pub fn read_run_length_encoding_chunk<B: PacketBuffer>(
315 buf: &mut B,
316) -> Result<RunLengthEncodingChunk> {
317 let symbol = buf
318 .read_u2()
319 .context("packet status symbol")?
320 .try_into()
321 .context("convert u2 to packet status symbol")?;
322 let run_length = buf.read_u13::<NetworkOrder>().context("run length")?;
323
324 Ok(RunLengthEncodingChunk { symbol, run_length })
325}
326
327enum SomePacketStatusChunk {
328 StatusVectorChunk(StatusVectorChunk),
329 RunLengthEncodingChunk(RunLengthEncodingChunk),
330}
331
332enum SomePacketStatusChunkIterator {
333 RunLengthEncodingChunkIterator(RunLengthEncodingIterator),
334 StatusVectorChunkIterator(<StatusVectorChunk as IntoIterator>::IntoIter),
335}
336
337impl Iterator for SomePacketStatusChunkIterator {
338 type Item = PacketStatusSymbol;
339
340 fn next(&mut self) -> Option<Self::Item> {
341 match self {
342 SomePacketStatusChunkIterator::StatusVectorChunkIterator(i) => i.next(),
343 SomePacketStatusChunkIterator::RunLengthEncodingChunkIterator(i) => i.next(),
344 }
345 }
346}
347
348impl SomePacketStatusChunk {
349 fn num_symbols(&self) -> u16 {
350 match self {
351 SomePacketStatusChunk::StatusVectorChunk(svc) => svc.0.len() as u16,
352 SomePacketStatusChunk::RunLengthEncodingChunk(rlec) => rlec.run_length.into(),
353 }
354 }
355}
356
357impl IntoIterator for SomePacketStatusChunk {
358 type Item = PacketStatusSymbol;
359
360 type IntoIter = SomePacketStatusChunkIterator;
361
362 fn into_iter(self) -> Self::IntoIter {
363 match self {
364 SomePacketStatusChunk::StatusVectorChunk(svc) => {
365 SomePacketStatusChunkIterator::StatusVectorChunkIterator(svc.into_iter())
366 }
367 SomePacketStatusChunk::RunLengthEncodingChunk(rlec) => {
368 SomePacketStatusChunkIterator::RunLengthEncodingChunkIterator(rlec.into_iter())
369 }
370 }
371 }
372}
373
374fn read_some_packet_status_chunk<B: PacketBuffer>(
375 buf: &mut B,
376 max_symbol_count: usize,
377) -> Result<SomePacketStatusChunk> {
378 let chunk_type = buf.read_u1().context("chunk type")?;
379 match chunk_type {
380 u1::ZERO => read_run_length_encoding_chunk(buf)
381 .map(SomePacketStatusChunk::RunLengthEncodingChunk)
382 .context("run length encoding chunk"),
383 u1::ONE => read_status_vector_chunk(buf, max_symbol_count)
384 .map(SomePacketStatusChunk::StatusVectorChunk)
385 .context("status vector chunk"),
386 _ => unreachable!(),
387 }
388}
389
390#[cfg(test)]
391mod test {
392 use bit_cursor::{bit_cursor::BitCursor, nsw_types::u24};
393 use bitvec::{bits, order::Msb0, vec::BitVec};
394
395 use crate::rtcp::rtcp_fb_tcc::{PacketReport, PacketStatusSymbol};
396
397 use super::{read_rtcp_fb_tcc_data, read_status_vector_chunk};
398
399 #[test]
400 fn test_sv_chunk_1_bit_symbols() {
401 let chunk = bits!(u8, Msb0; 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1);
402 let mut cursor = BitCursor::new(chunk);
403
404 let sv_chunk = read_status_vector_chunk(&mut cursor, 14).unwrap();
405 assert_eq!(sv_chunk.0.len(), 14);
406 assert!(cursor.remaining_slice().is_empty());
407 assert_eq!(
408 sv_chunk.0,
409 vec![
410 PacketStatusSymbol::ReceivedSmallDelta,
411 PacketStatusSymbol::ReceivedSmallDelta,
412 PacketStatusSymbol::NotReceived,
413 PacketStatusSymbol::NotReceived,
414 PacketStatusSymbol::ReceivedSmallDelta,
415 PacketStatusSymbol::ReceivedSmallDelta,
416 PacketStatusSymbol::NotReceived,
417 PacketStatusSymbol::NotReceived,
418 PacketStatusSymbol::ReceivedSmallDelta,
419 PacketStatusSymbol::ReceivedSmallDelta,
420 PacketStatusSymbol::NotReceived,
421 PacketStatusSymbol::NotReceived,
422 PacketStatusSymbol::ReceivedSmallDelta,
423 PacketStatusSymbol::ReceivedSmallDelta,
424 ]
425 );
426 }
427
428 #[test]
429 fn test_sv_chunk_1_bit_symbols_with_limit() {
430 let chunk = bits!(u8, Msb0; 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1);
431 let mut cursor = BitCursor::new(chunk);
432
433 let sv_chunk = read_status_vector_chunk(&mut cursor, 3).unwrap();
434 assert_eq!(sv_chunk.0.len(), 3);
435 assert!(cursor.remaining_slice().is_empty());
436 assert_eq!(
437 sv_chunk.0,
438 vec![
439 PacketStatusSymbol::ReceivedSmallDelta,
440 PacketStatusSymbol::ReceivedSmallDelta,
441 PacketStatusSymbol::NotReceived,
442 ]
443 );
444 }
445
446 #[test]
447 fn test_sv_chunk_2_bit_symbols() {
448 let chunk = bits!(u8, Msb0; 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0);
449 let mut cursor = BitCursor::new(chunk);
450
451 let sv_chunk = read_status_vector_chunk(&mut cursor, 14).unwrap();
452 assert_eq!(sv_chunk.0.len(), 7);
453 assert!(cursor.remaining_slice().is_empty());
454 assert_eq!(
455 sv_chunk.0,
456 vec![
457 PacketStatusSymbol::NotReceived,
458 PacketStatusSymbol::ReceivedSmallDelta,
459 PacketStatusSymbol::ReceivedLargeOrNegativeDelta,
460 PacketStatusSymbol::NotReceived,
461 PacketStatusSymbol::ReceivedSmallDelta,
462 PacketStatusSymbol::ReceivedLargeOrNegativeDelta,
463 PacketStatusSymbol::NotReceived,
464 ]
465 );
466 }
467
468 #[test]
469 fn test_read_tcc_fb_data() {
470 #[rustfmt::skip]
471 let data_buf = [
472 0x01, 0x81, 0x00, 0x08, 0x19, 0xae, 0xe8, 0x45,
473 0xd9, 0x55, 0x20, 0x01, 0xa8, 0xff, 0xfc, 0x04,
474 0x00, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 00
475 ];
476 let mut cursor = BitCursor::new(BitVec::<u8, Msb0>::from_slice(&data_buf));
477 let (packet_reports, reference_time, feedback_packet_count) =
478 read_rtcp_fb_tcc_data(&mut cursor).unwrap();
479
480 assert_eq!(reference_time, u24::new(1683176));
481 assert_eq!(feedback_packet_count, 69);
482 assert_eq!(
483 packet_reports,
484 [
485 PacketReport::ReceivedPacketSmallDelta {
486 seq_num: 385,
487 delta_ticks: 168,
488 },
489 PacketReport::ReceivedPacketLargeOrNegativeDelta {
490 seq_num: 386,
491 delta_ticks: -4,
492 },
493 PacketReport::ReceivedPacketSmallDelta {
494 seq_num: 387,
495 delta_ticks: 4,
496 },
497 PacketReport::ReceivedPacketSmallDelta {
498 seq_num: 388,
499 delta_ticks: 0,
500 },
501 PacketReport::ReceivedPacketSmallDelta {
502 seq_num: 389,
503 delta_ticks: 80,
504 },
505 PacketReport::ReceivedPacketSmallDelta {
506 seq_num: 390,
507 delta_ticks: 4,
508 },
509 PacketReport::ReceivedPacketSmallDelta {
510 seq_num: 391,
511 delta_ticks: 0,
512 },
513 PacketReport::ReceivedPacketSmallDelta {
514 seq_num: 392,
515 delta_ticks: 0,
516 },
517 ]
518 );
519 dbg!(packet_reports);
520 }
521}