1use parsely_rs::*;
2
3use super::{
4 rtcp_fb_header::RtcpFbHeader, rtcp_fb_packet::RtcpFbPsPacket, rtcp_header::RtcpHeader,
5};
6
7#[derive(Debug, ParselyRead, ParselyWrite, PartialEq)]
26#[parsely_read(required_context("header: RtcpHeader", "fb_header: RtcpFbHeader"))]
27pub struct RtcpFbFirPacket {
28 #[parsely_read(assign_from = "header")]
29 #[parsely(assertion = "|header: &RtcpHeader| header.report_count == RtcpFbFirPacket::FMT")]
30 #[parsely_write(sync_with("self.payload_length_bytes()", "RtcpFbFirPacket::FMT"))]
31 pub header: RtcpHeader,
32 #[parsely_read(assign_from = "fb_header")]
33 #[parsely(assertion = "|fb_header: &RtcpFbHeader| fb_header.media_source_ssrc == 0")]
34 pub fb_header: RtcpFbHeader,
35 #[parsely_read(while_pred = "buf.remaining_bytes() > 0")]
36 pub fcis: Vec<RtcpFbFirFci>,
37}
38
39impl RtcpFbFirPacket {
40 pub const FMT: u5 = u5::new(4);
41
42 pub fn add_fci(mut self, fci: RtcpFbFirFci) -> Self {
43 self.fcis.push(fci);
44 self
45 }
46
47 pub fn payload_length_bytes(&self) -> u16 {
48 (self.fcis.len() * 8) as u16
50 }
51}
52
53impl Default for RtcpFbFirPacket {
54 fn default() -> Self {
55 Self {
56 header: RtcpHeader::default()
57 .packet_type(RtcpFbPsPacket::PT)
58 .report_count(RtcpFbFirPacket::FMT),
59 fb_header: RtcpFbHeader::default().media_source_ssrc(0),
60 fcis: Default::default(),
61 }
62 }
63}
64
65#[derive(Debug, ParselyRead, ParselyWrite, PartialEq)]
66pub struct RtcpFbFirFci {
67 ssrc: u32,
68 seq_num: u8,
69 _reserved: u24,
70}
71
72impl RtcpFbFirFci {
73 pub const SIZE_BYTES: usize = 8;
74
75 pub fn new(ssrc: u32, seq_num: u8) -> Self {
76 Self {
77 ssrc,
78 seq_num,
79 _reserved: u24::new(0),
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use crate::rtcp::rtcp_fb_packet::RtcpFbPsPacket;
87
88 use super::*;
89
90 #[test]
91 fn test_read_fci() {
92 #[rustfmt::skip]
93 let data = vec![
94 0x00, 0x00, 0x00, 0x2a,
96 0x01,
98 0x00, 0x00, 0x00
100 ];
101
102 let mut buf = Bits::from_owner_bytes(data);
103
104 let fci = RtcpFbFirFci::read::<NetworkOrder>(&mut buf, ()).expect("successful read");
105 assert_eq!(fci.ssrc, 42);
106 assert_eq!(fci.seq_num, 1);
107 }
108
109 #[test]
110 fn test_write_fci() {
111 let fci = RtcpFbFirFci::new(42, 1);
112 let mut buf_mut = BitsMut::new();
113
114 fci.write::<NetworkOrder>(&mut buf_mut, ())
115 .expect("successful write");
116 let mut buf = buf_mut.freeze();
117 let read_fci = RtcpFbFirFci::read::<NetworkOrder>(&mut buf, ()).expect("successful read");
118 assert_eq!(fci, read_fci);
119 }
120
121 #[test]
122 fn test_read_rtcp_fb_fir_packet() {
123 #[rustfmt::skip]
124 let data = vec![
125 0x00, 0x00, 0x00, 0x2a,
127 0x01,
129 0x00, 0x00, 0x00
131 ];
132 let mut buf = Bits::from_owner_bytes(data);
133 let header = RtcpHeader {
134 report_count: RtcpFbFirPacket::FMT,
135 packet_type: RtcpFbPsPacket::PT,
136 length_field: 4,
137 ..Default::default()
138 };
139 let fb_header = RtcpFbHeader::new(42, 0);
140
141 let fb_fir_packet = RtcpFbFirPacket::read::<NetworkOrder>(&mut buf, (header, fb_header))
142 .expect("successful read");
143 assert_eq!(buf.remaining_bytes(), 0);
144 assert_eq!(fb_fir_packet.fcis.len(), 1);
145 let fci = &fb_fir_packet.fcis[0];
146 assert_eq!(fci.ssrc, 42);
147 assert_eq!(fci.seq_num, 1);
148 }
149
150 #[test]
151 fn test_read_rtcp_fb_fir_packet_multiple_fcis() {
152 #[rustfmt::skip]
153 let data = vec![
154 0x00, 0x00, 0x00, 0x2a,
156 0x01,
158 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x2b,
162 0x02,
164 0x00, 0x00, 0x00,
166 ];
167 let mut buf = Bits::from_owner_bytes(data);
168 let header = RtcpHeader {
169 report_count: RtcpFbFirPacket::FMT,
170 packet_type: RtcpFbPsPacket::PT,
171 length_field: 6,
172 ..Default::default()
173 };
174 let fb_header = RtcpFbHeader::new(42, 0);
175
176 let fb_fir_packet = RtcpFbFirPacket::read::<NetworkOrder>(&mut buf, (header, fb_header))
177 .expect("successful read");
178 assert_eq!(buf.remaining_bytes(), 0);
179 assert_eq!(fb_fir_packet.fcis.len(), 2);
180 let fci = &fb_fir_packet.fcis[0];
181 assert_eq!(fci.ssrc, 42);
182 assert_eq!(fci.seq_num, 1);
183 let fci = &fb_fir_packet.fcis[1];
184 assert_eq!(fci.ssrc, 43);
185 assert_eq!(fci.seq_num, 2);
186 }
187
188 #[test]
189 fn test_default() {
190 let rtcp_fb_fir = RtcpFbFirPacket::default();
191 assert_eq!(RtcpFbPsPacket::PT, rtcp_fb_fir.header.packet_type);
192 assert_eq!(RtcpFbFirPacket::FMT, rtcp_fb_fir.header.report_count);
193 assert_eq!(0, rtcp_fb_fir.fb_header.media_source_ssrc);
194 }
195
196 #[test]
197 fn test_sync() {
198 let mut rtcp_fb_fir = RtcpFbFirPacket::default()
199 .add_fci(RtcpFbFirFci::new(42, 1))
200 .add_fci(RtcpFbFirFci::new(43, 2));
201
202 rtcp_fb_fir.sync(()).expect("successful sync");
203 assert_eq!(RtcpFbPsPacket::PT, rtcp_fb_fir.header.packet_type);
204 assert_eq!(RtcpFbFirPacket::FMT, rtcp_fb_fir.header.report_count);
205 assert_eq!(0, rtcp_fb_fir.fb_header.media_source_ssrc);
206 }
207
208 #[test]
209 fn test_write() {
210 let mut rtcp_fb_fir = RtcpFbFirPacket::default()
211 .add_fci(RtcpFbFirFci::new(42, 1))
212 .add_fci(RtcpFbFirFci::new(43, 2));
213 rtcp_fb_fir.sync(()).unwrap();
214 let mut buf_mut = BitsMut::new();
215
216 rtcp_fb_fir.write::<NetworkOrder>(&mut buf_mut, ()).unwrap();
217 let mut buf = buf_mut.freeze();
218
219 let rtcp_header = RtcpHeader::read::<NetworkOrder>(&mut buf, ()).unwrap();
220 let rtcp_fb_header = RtcpFbHeader::read::<NetworkOrder>(&mut buf, ()).unwrap();
221 let read_rtcp_fb_fir =
222 RtcpFbFirPacket::read::<NetworkOrder>(&mut buf, (rtcp_header, rtcp_fb_header)).unwrap();
223 assert_eq!(rtcp_fb_fir, read_rtcp_fb_fir);
224 }
225}