rtc_rtcp/payload_feedbacks/full_intra_request/
mod.rs1#[cfg(test)]
2mod full_intra_request_test;
3
4use crate::{header::*, packet::*, util::*};
5use shared::{
6 error::{Error, Result},
7 marshal::{Marshal, MarshalSize, Unmarshal},
8};
9
10use bytes::{Buf, BufMut};
11use std::any::Any;
12use std::fmt;
13
14#[derive(Debug, PartialEq, Eq, Default, Clone)]
16pub struct FirEntry {
17 pub ssrc: u32,
19 pub sequence_number: u8,
21}
22
23#[derive(Debug, PartialEq, Eq, Default, Clone)]
27pub struct FullIntraRequest {
28 pub sender_ssrc: u32,
30 pub media_ssrc: u32,
32 pub fir: Vec<FirEntry>,
34}
35
36const FIR_OFFSET: usize = 8;
37
38impl fmt::Display for FullIntraRequest {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 let mut out = format!("FullIntraRequest {} {}", self.sender_ssrc, self.media_ssrc);
41 for e in &self.fir {
42 out += format!(" ({} {})", e.ssrc, e.sequence_number).as_str();
43 }
44 write!(f, "{out}")
45 }
46}
47
48impl Packet for FullIntraRequest {
49 fn header(&self) -> Header {
50 Header {
51 padding: get_padding_size(self.raw_size()) != 0,
52 count: FORMAT_FIR,
53 packet_type: PacketType::PayloadSpecificFeedback,
54 length: ((self.marshal_size() / 4) - 1) as u16,
55 }
56 }
57
58 fn destination_ssrc(&self) -> Vec<u32> {
60 let mut ssrcs: Vec<u32> = Vec::with_capacity(self.fir.len());
61 for entry in &self.fir {
62 ssrcs.push(entry.ssrc);
63 }
64 ssrcs
65 }
66
67 fn raw_size(&self) -> usize {
68 HEADER_LENGTH + FIR_OFFSET + self.fir.len() * 8
69 }
70
71 fn as_any(&self) -> &dyn Any {
72 self
73 }
74
75 fn equal(&self, other: &dyn Packet) -> bool {
76 other.as_any().downcast_ref::<FullIntraRequest>() == Some(self)
77 }
78
79 fn cloned(&self) -> Box<dyn Packet> {
80 Box::new(self.clone())
81 }
82}
83
84impl MarshalSize for FullIntraRequest {
85 fn marshal_size(&self) -> usize {
86 let l = self.raw_size();
87 l + get_padding_size(l)
89 }
90}
91
92impl Marshal for FullIntraRequest {
93 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
95 if buf.remaining_mut() < self.marshal_size() {
96 return Err(Error::BufferTooShort);
97 }
98
99 let h = self.header();
100 let n = h.marshal_to(buf)?;
101 buf = &mut buf[n..];
102
103 buf.put_u32(self.sender_ssrc);
104 buf.put_u32(self.media_ssrc);
105
106 for fir in self.fir.iter() {
107 buf.put_u32(fir.ssrc);
108 buf.put_u8(fir.sequence_number);
109 buf.put_u8(0);
110 buf.put_u16(0);
111 }
112
113 if h.padding {
114 put_padding(buf, self.raw_size());
115 }
116
117 Ok(self.marshal_size())
118 }
119}
120
121impl Unmarshal for FullIntraRequest {
122 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
124 where
125 Self: Sized,
126 B: Buf,
127 {
128 let raw_packet_len = raw_packet.remaining();
129 if raw_packet_len < FIR_MIN_OCTET_COUNT {
130 return Err(Error::PacketTooShort);
131 }
132
133 let h = Header::unmarshal(raw_packet)?;
134 if (HEADER_LENGTH + 4 * (h.length as usize)) < FIR_MIN_OCTET_COUNT {
135 return Err(Error::InvalidHeader);
136 }
137
138 if raw_packet_len < (HEADER_LENGTH + 4 * (h.length as usize)) {
139 return Err(Error::PacketTooShort);
140 }
141
142 if h.packet_type != PacketType::PayloadSpecificFeedback || h.count != FORMAT_FIR {
143 return Err(Error::WrongType);
144 }
145
146 let sender_ssrc = raw_packet.get_u32();
147 let media_ssrc = raw_packet.get_u32();
148
149 let mut i = HEADER_LENGTH + FIR_OFFSET;
150 let mut fir = vec![];
151 while i < HEADER_LENGTH + (h.length * 4) as usize {
152 if raw_packet.remaining() < 8 {
154 return Err(Error::PacketTooShort);
155 }
156
157 fir.push(FirEntry {
158 ssrc: raw_packet.get_u32(),
159 sequence_number: raw_packet.get_u8(),
160 });
161 raw_packet.get_u8();
162 raw_packet.get_u16();
163
164 i += 8;
165 }
166
167 if
168 raw_packet.has_remaining() {
170 raw_packet.advance(raw_packet.remaining());
171 }
172
173 Ok(FullIntraRequest {
174 sender_ssrc,
175 media_ssrc,
176 fir,
177 })
178 }
179}