1use parsely_rs::*;
2
3use super::{rtcp_fb_header::RtcpFbHeader, rtcp_header::RtcpHeader};
4
5const U1_ZERO: u1 = u1::new(0);
6const U1_ONE: u1 = u1::new(1);
7
8const U2_ZERO: u2 = u2::new(0);
9const U2_ONE: u2 = u2::new(1);
10const U2_TWO: u2 = u2::new(2);
11
12#[derive(Debug)]
47pub struct RtcpFbTccPacket {
48 pub header: RtcpHeader,
49 pub fb_header: RtcpFbHeader,
50 pub packet_reports: Vec<PacketReport>,
51 pub reference_time: u24,
52 pub feedback_packet_count: u8,
53}
54
55impl RtcpFbTccPacket {
56 pub const FMT: u5 = u5::new(15);
57
58 pub fn payload_length_bytes(&self) -> usize {
59 todo!()
60 }
61}
62
63impl<B: BitBuf> ParselyRead<B> for RtcpFbTccPacket {
64 type Ctx = (RtcpHeader, RtcpFbHeader);
65
66 fn read<T: ByteOrder>(buf: &mut B, (header, fb_header): Self::Ctx) -> ParselyResult<Self> {
67 let bytes_remaining_start = buf.remaining_bytes();
68 let base_seq_num = buf.get_u16::<T>().context("Reading field 'base_seq_num'")?;
69 let packet_status_count = buf
70 .get_u16::<T>()
71 .context("Reading field 'packet_status_count'")?;
72 let reference_time = buf
73 .get_u24::<T>()
74 .context("Reading field 'reference_time'")?;
75 let feedback_packet_count = buf
76 .get_u8()
77 .context("Reading field 'feedback_packet_count'")?;
78
79 let mut num_status_remaining = packet_status_count;
80 let mut chunks: Vec<SomePacketStatusChunk> = vec![];
81 while num_status_remaining > 0 {
82 let chunk = SomePacketStatusChunk::read::<T>(buf, (num_status_remaining as usize,))
83 .context("packet status chunk")?;
84 num_status_remaining -= chunk.num_symbols();
85 chunks.push(chunk);
86 }
87 let mut packet_reports: Vec<PacketReport> =
88 Vec::with_capacity(packet_status_count as usize);
89 let mut curr_seq_num = base_seq_num;
90 for chunk in &chunks {
91 for status_symbol in chunk.iter() {
92 match status_symbol.delta_size_bytes() {
93 0 => packet_reports.push(PacketReport::UnreceivedPacket {
94 seq_num: curr_seq_num,
95 }),
96 1 => {
97 let delta_ticks = buf
98 .get_u8()
99 .with_context(|| format!("delta ticks for packet {curr_seq_num}"))?;
100 packet_reports.push(PacketReport::ReceivedPacketSmallDelta {
101 seq_num: curr_seq_num,
102 delta_ticks,
103 })
104 }
105 2 => {
106 let delta_ticks = buf
107 .get_u16::<T>()
108 .with_context(|| format!("delta ticks for packet {curr_seq_num}"))?
109 as i16;
110 packet_reports.push(PacketReport::ReceivedPacketLargeOrNegativeDelta {
111 seq_num: curr_seq_num,
112 delta_ticks,
113 })
114 }
115 delta_size_bytes => bail!("Invalid delta size: {delta_size_bytes} bytes"),
116 }
117 curr_seq_num = curr_seq_num.wrapping_add(1);
118 }
119 }
120 while (bytes_remaining_start - buf.remaining_bytes()) % 4 != 0 {
121 let _ = buf.get_u8().context("padding")?;
122 }
123 Ok(RtcpFbTccPacket {
124 header,
125 fb_header,
126 packet_reports,
127 reference_time,
128 feedback_packet_count,
129 })
130 }
131}
132
133impl<B: BitBufMut> ParselyWrite<B> for RtcpFbTccPacket {
134 type Ctx = ();
135
136 fn write<T: ByteOrder>(&self, buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<()> {
137 self.header.write::<T>(buf, ()).context("header")?;
138 self.fb_header.write::<T>(buf, ()).context("fb header")?;
139
140 if self.packet_reports.is_empty() {
141 return Ok(());
142 }
143 let base_seq_num = self.packet_reports[0].seq_num();
144 let packet_status_count = self.packet_reports.len() as u16;
145 buf.put_u16::<T>(base_seq_num).context("base_seq_num")?;
146 buf.put_u16::<T>(packet_status_count)
147 .context("packet_status_count")?;
148 buf.put_u24::<T>(self.reference_time)
149 .context("reference_time")?;
150 buf.put_u8(self.feedback_packet_count)
151 .context("feedback_packet_count")?;
152 todo!()
153 }
154}
155
156impl StateSync for RtcpFbTccPacket {
157 type SyncCtx = ();
158
159 fn sync(&mut self, _sync_ctx: Self::SyncCtx) -> ParselyResult<()> {
160 self.header
161 .sync((self.payload_length_bytes() as u16, Self::FMT))?;
162
163 self.packet_reports.sort_by_key(|pr| pr.seq_num());
164
165 Ok(())
166 }
167}
168
169#[derive(Debug, PartialEq)]
263pub enum PacketReport {
264 UnreceivedPacket { seq_num: u16 },
265 ReceivedPacketSmallDelta { seq_num: u16, delta_ticks: u8 },
266 ReceivedPacketLargeOrNegativeDelta { seq_num: u16, delta_ticks: i16 },
267}
268
269impl PacketReport {
270 pub fn seq_num(&self) -> u16 {
271 match self {
272 Self::UnreceivedPacket { seq_num } => *seq_num,
273 Self::ReceivedPacketSmallDelta { seq_num, .. } => *seq_num,
274 Self::ReceivedPacketLargeOrNegativeDelta { seq_num, .. } => *seq_num,
275 }
276 }
277
278 pub fn symbol(&self) -> PacketStatusSymbol {
279 match self {
280 PacketReport::UnreceivedPacket { .. } => PacketStatusSymbol::NotReceived,
281 PacketReport::ReceivedPacketSmallDelta { .. } => PacketStatusSymbol::ReceivedSmallDelta,
282 PacketReport::ReceivedPacketLargeOrNegativeDelta { .. } => {
283 PacketStatusSymbol::ReceivedLargeOrNegativeDelta
284 }
285 }
286 }
287}
288
289#[derive(Copy, Clone, Debug, PartialEq, Eq)]
290pub enum PacketStatusSymbol {
291 NotReceived = 0,
292 ReceivedSmallDelta = 1,
293 ReceivedLargeOrNegativeDelta = 2,
294}
295
296impl PacketStatusSymbol {
297 pub(crate) fn delta_size_bytes(&self) -> u8 {
307 match self {
308 PacketStatusSymbol::NotReceived => 0,
309 PacketStatusSymbol::ReceivedSmallDelta => 1,
310 PacketStatusSymbol::ReceivedLargeOrNegativeDelta => 2,
311 }
312 }
313}
314
315impl From<u1> for PacketStatusSymbol {
316 fn from(value: u1) -> Self {
317 match value {
318 U1_ZERO => PacketStatusSymbol::NotReceived,
319 U1_ONE => PacketStatusSymbol::ReceivedSmallDelta,
320 _ => unreachable!(),
321 }
322 }
323}
324
325impl TryInto<u1> for &PacketStatusSymbol {
326 type Error = anyhow::Error;
327
328 fn try_into(self) -> std::prelude::v1::Result<u1, Self::Error> {
329 match self {
330 PacketStatusSymbol::NotReceived => Ok(U1_ZERO),
331 PacketStatusSymbol::ReceivedSmallDelta => Ok(U1_ONE),
332 PacketStatusSymbol::ReceivedLargeOrNegativeDelta => Err(anyhow!(
333 "PacketStatusSymbol::ReceivedLargeOrNegativeDelta can't be encoded into a u1"
334 )),
335 }
336 }
337}
338
339impl TryInto<u1> for PacketStatusSymbol {
340 type Error = anyhow::Error;
341
342 fn try_into(self) -> std::prelude::v1::Result<u1, Self::Error> {
343 (&self).try_into()
344 }
345}
346
347impl TryFrom<u2> for PacketStatusSymbol {
348 type Error = anyhow::Error;
349
350 fn try_from(value: u2) -> std::prelude::v1::Result<Self, Self::Error> {
351 match value {
352 U2_ZERO => Ok(PacketStatusSymbol::NotReceived),
353 U2_ONE => Ok(PacketStatusSymbol::ReceivedSmallDelta),
354 U2_TWO => Ok(PacketStatusSymbol::ReceivedLargeOrNegativeDelta),
355 pss => Err(anyhow!("Invalid 2 bit packet status symbol: {pss}")),
356 }
357 }
358}
359
360impl From<&PacketStatusSymbol> for u2 {
361 fn from(val: &PacketStatusSymbol) -> Self {
362 match val {
363 PacketStatusSymbol::NotReceived => u2::new(0),
364 PacketStatusSymbol::ReceivedSmallDelta => u2::new(1),
365 PacketStatusSymbol::ReceivedLargeOrNegativeDelta => u2::new(2),
366 }
367 }
368}
369
370impl From<PacketStatusSymbol> for u2 {
371 fn from(val: PacketStatusSymbol) -> Self {
372 (&val).into()
373 }
374}
375
376#[derive(Debug, Clone, PartialEq)]
400pub struct StatusVectorChunk(pub(crate) Vec<PacketStatusSymbol>);
401
402impl StatusVectorChunk {
403 fn has_two_bit_symbols(&self) -> bool {
404 self.0
405 .iter()
406 .any(|ss| matches!(ss, PacketStatusSymbol::ReceivedLargeOrNegativeDelta))
407 }
408
409 fn iter(&self) -> std::slice::Iter<'_, PacketStatusSymbol> {
410 self.0.iter()
411 }
412}
413
414impl<B: BitBuf> ParselyRead<B> for StatusVectorChunk {
416 type Ctx = (usize,);
417
418 fn read<T: ByteOrder>(buf: &mut B, (max_symbol_count,): Self::Ctx) -> ParselyResult<Self> {
419 let symbol_size = buf.get_u1().context("symbol size")?;
420 let mut packet_status_symbols = match symbol_size {
421 s if s == 0 => {
422 let mut symbols = Vec::with_capacity(14);
424 for i in 0..14 {
425 let symbol: PacketStatusSymbol = buf
426 .get_u1()
427 .with_context(|| format!("packet status symbol {i}"))
428 .map(|v| v.into())?;
429 symbols.push(symbol);
430 }
431 symbols
432 }
433 s if s == 1 => {
434 let mut symbols = Vec::with_capacity(7);
436 for i in 0..7 {
437 let symbol: PacketStatusSymbol = buf
438 .get_u2()
439 .with_context(|| format!("packet status symbol {i}"))?
440 .try_into()
441 .context("converting u2 to packet status symbol")?;
442 symbols.push(symbol);
443 }
444 symbols
445 }
446 _ => unreachable!("u1 can only be 1 or 0"),
447 };
448
449 packet_status_symbols.truncate(max_symbol_count);
450
451 Ok(StatusVectorChunk(packet_status_symbols))
452 }
453}
454
455impl<B: BitBufMut> ParselyWrite<B> for StatusVectorChunk {
456 type Ctx = ();
457
458 fn write<T: ByteOrder>(&self, buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<()> {
459 buf.put_u1(u1::new(1)).context("SV chunk type")?;
460 if self.has_two_bit_symbols() {
461 buf.put_u1(u1::new(1)).context("SV chunk symbol size")?;
462 for (i, symbol) in self.iter().enumerate() {
463 buf.put_u2(symbol.into())
464 .with_context(|| format!("2 bit sv chunk symbol {i}"))?;
465 }
466 } else {
467 buf.put_u1(u1::new(0)).context("SV chunk symbol size")?;
468 for (i, symbol) in self.iter().enumerate() {
469 buf.put_u1(
470 symbol
471 .try_into()
472 .context("Trying to convert status symbol to u1")?,
473 )
474 .with_context(|| format!("2 bit sv chunk symbol {i}"))?;
475 }
476 }
477 Ok(())
478 }
479}
480
481impl_stateless_sync!(StatusVectorChunk);
482
483#[derive(Debug, Clone, PartialEq, Eq)]
500pub struct RunLengthEncodingChunk {
501 pub symbol: PacketStatusSymbol,
502 pub run_length: u13,
503}
504
505impl<B: BitBuf> ParselyRead<B> for RunLengthEncodingChunk {
507 type Ctx = ();
508
509 fn read<T: ByteOrder>(buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<Self> {
510 let symbol = buf
511 .get_u2()
512 .context("Reading run length encoding symbol")?
513 .try_into()
514 .context("Converting u2 to packet status symbol")?;
515
516 let run_length = buf.get_u13::<T>().context("Reading run length")?;
517
518 Ok(RunLengthEncodingChunk { symbol, run_length })
519 }
520}
521
522impl<B: BitBufMut> ParselyWrite<B> for RunLengthEncodingChunk {
523 type Ctx = ();
524
525 fn write<T: ByteOrder>(&self, buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<()> {
526 buf.put_u1(u1::new(0)).context("rle chunk type")?;
527 buf.put_u2(self.symbol.into()).context("rle chunk symbol")?;
528 buf.put_u13::<T>(self.run_length)
529 .context("rle chunk run length")?;
530
531 Ok(())
532 }
533}
534
535impl_stateless_sync!(RunLengthEncodingChunk);
536
537#[derive(Debug, Clone)]
538pub(crate) enum SomePacketStatusChunk {
539 StatusVectorChunk(StatusVectorChunk),
540 RunLengthEncodingChunk(RunLengthEncodingChunk),
541}
542
543pub(crate) enum SomePacketStatusChunkIterator<'a> {
544 StatusVector(std::slice::Iter<'a, PacketStatusSymbol>),
545 RunLength(std::iter::Repeat<PacketStatusSymbol>, usize), }
547
548impl Iterator for SomePacketStatusChunkIterator<'_> {
549 type Item = PacketStatusSymbol;
550
551 fn next(&mut self) -> Option<Self::Item> {
552 match self {
553 SomePacketStatusChunkIterator::StatusVector(iter) => iter.next().copied(),
554 SomePacketStatusChunkIterator::RunLength(iter, remaining) => {
555 if *remaining == 0 {
556 None
557 } else {
558 *remaining -= 1;
559 iter.next()
560 }
561 }
562 }
563 }
564}
565
566impl SomePacketStatusChunk {
567 pub(crate) fn num_symbols(&self) -> u16 {
568 match self {
569 SomePacketStatusChunk::StatusVectorChunk(svc) => svc.0.len() as u16,
570 SomePacketStatusChunk::RunLengthEncodingChunk(rlec) => rlec.run_length.into(),
571 }
572 }
573
574 pub fn iter(&self) -> SomePacketStatusChunkIterator<'_> {
575 match self {
576 SomePacketStatusChunk::StatusVectorChunk(StatusVectorChunk(vec)) => {
577 SomePacketStatusChunkIterator::StatusVector(vec.iter())
578 }
579 SomePacketStatusChunk::RunLengthEncodingChunk(chunk) => {
580 SomePacketStatusChunkIterator::RunLength(
581 std::iter::repeat(chunk.symbol),
582 chunk.run_length.into(),
583 )
584 }
585 }
586 }
587}
588
589impl<B: BitBuf> ParselyRead<B> for SomePacketStatusChunk {
590 type Ctx = (usize,);
591
592 fn read<T: ByteOrder>(buf: &mut B, (max_symbol_count,): Self::Ctx) -> ParselyResult<Self> {
593 let chunk_type = buf.get_u1().context("chunk type")?;
594 match chunk_type {
595 ct if ct == 0 => RunLengthEncodingChunk::read::<T>(buf, ())
596 .map(SomePacketStatusChunk::RunLengthEncodingChunk)
597 .context("run length encoding chunk"),
598 ct if ct == 1 => StatusVectorChunk::read::<T>(buf, (max_symbol_count,))
599 .map(SomePacketStatusChunk::StatusVectorChunk)
600 .context("status vector chunk"),
601 _ => unreachable!(),
602 }
603 }
604}
605
606impl<B: BitBufMut> ParselyWrite<B> for SomePacketStatusChunk {
607 type Ctx = ();
608
609 fn write<T: ByteOrder>(&self, buf: &mut B, _ctx: Self::Ctx) -> ParselyResult<()> {
610 match self {
611 SomePacketStatusChunk::RunLengthEncodingChunk(rle_chunk) => {
612 rle_chunk.write::<T>(buf, ())?
613 }
614 SomePacketStatusChunk::StatusVectorChunk(sv_chunk) => sv_chunk.write::<T>(buf, ())?,
615 }
616 Ok(())
617 }
618}
619
620impl_stateless_sync!(SomePacketStatusChunk);
621
622#[cfg(test)]
623mod test {
624 use super::*;
625 use bits_io::bits;
626 #[test]
629 fn test_sv_chunk_1_bit_symbols() {
630 let chunk_data = bits!(1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1);
631 let mut bits = Bits::copy_from_bit_slice(chunk_data);
632 bits.advance_bits(1);
635
636 let sv_chunk = StatusVectorChunk::read::<NetworkOrder>(&mut bits, (14,)).unwrap();
637
638 assert_eq!(sv_chunk.0.len(), 14);
639 assert!(bits.is_empty());
640 assert_eq!(
641 sv_chunk.0,
642 vec![
643 PacketStatusSymbol::ReceivedSmallDelta,
644 PacketStatusSymbol::ReceivedSmallDelta,
645 PacketStatusSymbol::NotReceived,
646 PacketStatusSymbol::NotReceived,
647 PacketStatusSymbol::ReceivedSmallDelta,
648 PacketStatusSymbol::ReceivedSmallDelta,
649 PacketStatusSymbol::NotReceived,
650 PacketStatusSymbol::NotReceived,
651 PacketStatusSymbol::ReceivedSmallDelta,
652 PacketStatusSymbol::ReceivedSmallDelta,
653 PacketStatusSymbol::NotReceived,
654 PacketStatusSymbol::NotReceived,
655 PacketStatusSymbol::ReceivedSmallDelta,
656 PacketStatusSymbol::ReceivedSmallDelta,
657 ]
658 );
659
660 let mut bits_mut = BitsMut::new();
661 sv_chunk.write::<NetworkOrder>(&mut bits_mut, ()).unwrap();
662 assert_eq!(chunk_data, bits_mut.as_ref());
663 }
664
665 #[test]
666 fn test_sv_chunk_1_bit_symbols_with_limit() {
667 let mut chunk_data = bits!(0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1);
668
669 let sv_chunk = StatusVectorChunk::read::<NetworkOrder>(&mut chunk_data, (3,)).unwrap();
670 assert_eq!(sv_chunk.0.len(), 3);
671 assert!(chunk_data.is_empty());
672 assert_eq!(
673 sv_chunk.0,
674 vec![
675 PacketStatusSymbol::ReceivedSmallDelta,
676 PacketStatusSymbol::ReceivedSmallDelta,
677 PacketStatusSymbol::NotReceived,
678 ]
679 );
680 }
681
682 #[test]
683 fn test_sv_chunk_2_bit_symbols() {
684 let chunk_data = bits!(1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0);
685 let mut bits = Bits::copy_from_bit_slice(chunk_data);
686 bits.advance_bits(1);
687
688 let sv_chunk = StatusVectorChunk::read::<NetworkOrder>(&mut bits, (15,)).unwrap();
689 assert_eq!(sv_chunk.0.len(), 7);
690 assert!(bits.is_empty());
691 assert_eq!(
692 sv_chunk.0,
693 vec![
694 PacketStatusSymbol::NotReceived,
695 PacketStatusSymbol::ReceivedSmallDelta,
696 PacketStatusSymbol::ReceivedLargeOrNegativeDelta,
697 PacketStatusSymbol::NotReceived,
698 PacketStatusSymbol::ReceivedSmallDelta,
699 PacketStatusSymbol::ReceivedLargeOrNegativeDelta,
700 PacketStatusSymbol::NotReceived,
701 ]
702 );
703
704 let mut bits_mut = BitsMut::new();
705 sv_chunk.write::<NetworkOrder>(&mut bits_mut, ()).unwrap();
706 assert_eq!(chunk_data, bits_mut.as_ref());
707 }
708
709 #[test]
710 fn test_rle_chunk() {
711 let chunk_data = bits!(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1);
712 let mut bits = Bits::copy_from_bit_slice(chunk_data);
713 bits.advance_bits(1);
714
715 let rle_chunk = RunLengthEncodingChunk::read::<NetworkOrder>(&mut bits, ()).unwrap();
716 assert!(bits.is_empty());
717 assert_eq!(rle_chunk.symbol, PacketStatusSymbol::ReceivedSmallDelta);
718 assert_eq!(rle_chunk.run_length, 0b0000000010101);
719
720 let mut bits_mut = BitsMut::new();
721 rle_chunk.write::<NetworkOrder>(&mut bits_mut, ()).unwrap();
722 assert_eq!(chunk_data, bits_mut.as_ref());
723 }
724
725 #[test]
726 fn test_rtcp_fb_tcc_packet() {
727 #[rustfmt::skip]
728 let data_buf = [
729 0x01, 0x81, 0x00, 0x08,
731 0x19, 0xae, 0xe8, 0x45,
733
734 0xd9, 0x55, 0x20, 0x01,
735 0xa8, 0xff, 0xfc, 0x04,
736 0x00, 0x50, 0x04, 0x00,
737 0x00, 0x00, 0x00, 0x00
738 ];
739 let mut bits = Bits::copy_from_bytes(&data_buf[..]);
740 let tcc_packet = RtcpFbTccPacket::read::<NetworkOrder>(
741 &mut bits,
742 (RtcpHeader::default(), RtcpFbHeader::default()),
743 )
744 .unwrap();
745 assert_eq!(tcc_packet.reference_time, u24::new(1683176));
746 assert_eq!(tcc_packet.feedback_packet_count, 69);
747 assert_eq!(
748 tcc_packet.packet_reports,
749 [
750 PacketReport::ReceivedPacketSmallDelta {
751 seq_num: 385,
752 delta_ticks: 168,
753 },
754 PacketReport::ReceivedPacketLargeOrNegativeDelta {
755 seq_num: 386,
756 delta_ticks: -4,
757 },
758 PacketReport::ReceivedPacketSmallDelta {
759 seq_num: 387,
760 delta_ticks: 4,
761 },
762 PacketReport::ReceivedPacketSmallDelta {
763 seq_num: 388,
764 delta_ticks: 0,
765 },
766 PacketReport::ReceivedPacketSmallDelta {
767 seq_num: 389,
768 delta_ticks: 80,
769 },
770 PacketReport::ReceivedPacketSmallDelta {
771 seq_num: 390,
772 delta_ticks: 4,
773 },
774 PacketReport::ReceivedPacketSmallDelta {
775 seq_num: 391,
776 delta_ticks: 0,
777 },
778 PacketReport::ReceivedPacketSmallDelta {
779 seq_num: 392,
780 delta_ticks: 0,
781 },
782 ]
783 );
784 }
785}