Skip to content
File

Blob: firmware/vendor/str0m/src/rtp/rtcp/fir.rs

rust95 lines
1use super::list::private::WordSized;
2use super::{FeedbackMessageType, PayloadType, ReportList, RtcpHeader, RtcpPacket, RtcpType, Ssrc};
3 
4/// Full Intra Request (FIR).
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Fir {
7 /// Sender of this feedback. Mostly irrelevant, but part of RTCP packets.
8 pub sender_ssrc: Ssrc,
9 /// The SSRC needing a full codec restart.
10 pub reports: ReportList<FirEntry>,
11}
12 
13/// Entry reported needing a codec restart.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct FirEntry {
16 /// The SSRC needing a full codec restart.
17 pub ssrc: Ssrc,
18 /// Counter keeping track of which restart request this is.
19 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 // header
35 // sender SSRC
36 // media SSRC (set to 0)
37 // reports * FirEntry: SSRC + seqNo
38 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}