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