atm0s_custom_str0m/rtp/rtcp/
fir.rs1use super::list::private::WordSized;
2use super::{FeedbackMessageType, PayloadType, ReportList, RtcpHeader, RtcpPacket, RtcpType, Ssrc};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Fir {
7 pub sender_ssrc: Ssrc,
9 pub reports: ReportList<FirEntry>,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct FirEntry {
16 pub ssrc: Ssrc,
18 pub seq_no: u8,
20}
21
22impl RtcpPacket for Fir {
23 fn header(&self) -> RtcpHeader {
24 RtcpHeader {
25 rtcp_type: RtcpType::PayloadSpecificFeedback,
26 feedback_message_type: FeedbackMessageType::PayloadFeedback(
27 PayloadType::FullIntraRequest,
28 ),
29 words_less_one: (self.length_words() - 1) as u16,
30 }
31 }
32
33 fn length_words(&self) -> usize {
34 1 + 1 + 1 + self.reports.len() * 2
39 }
40
41 fn write_to(&self, buf: &mut [u8]) -> usize {
42 self.header().write_to(&mut buf[..4]);
43
44 buf[4..8].copy_from_slice(&self.sender_ssrc.to_be_bytes());
45
46 let media_ssrc = self.reports.iter().next().map(|s| *s.ssrc).unwrap_or(0);
47 buf[8..12].copy_from_slice(&media_ssrc.to_be_bytes());
48
49 let mut buf = &mut buf[12..];
50 for r in &self.reports {
51 buf[0..4].copy_from_slice(&r.ssrc.to_be_bytes());
52 buf[4..8].copy_from_slice(&[r.seq_no, 0, 0, 0]);
53 buf = &mut buf[8..];
54 }
55
56 4 + 4 + 4 + self.reports.len() * 8
57 }
58}
59
60impl WordSized for FirEntry {
61 fn word_size(&self) -> usize {
62 2
63 }
64}
65
66impl<'a> TryFrom<&'a [u8]> for Fir {
67 type Error = &'static str;
68
69 fn try_from(buf: &'a [u8]) -> Result<Self, Self::Error> {
70 if buf.len() < 16 {
71 return Err("Fir less than 16 bytes");
72 }
73
74 let sender_ssrc = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]).into();
75
76 let mut reports = ReportList::new();
77
78 let mut buf = &buf[8..];
79 let count = buf.len() / 8;
80 let max = count.min(31);
81
82 for _ in 0..max {
83 let ssrc = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]).into();
84 let seq_no = buf[4];
85 reports.push(FirEntry { ssrc, seq_no });
86 buf = &buf[8..];
87 }
88
89 Ok(Fir {
90 sender_ssrc,
91 reports,
92 })
93 }
94}