rtc_rtcp/payload_feedbacks/slice_loss_indication/
mod.rs1#[cfg(test)]
2mod slice_loss_indication_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
14const SLI_LENGTH: usize = 2;
15const SLI_OFFSET: usize = 8;
16
17#[derive(Debug, PartialEq, Eq, Default, Clone)]
20pub struct SliEntry {
21 pub first: u16,
23 pub number: u16,
25 pub picture: u8,
27}
28
29#[derive(Debug, PartialEq, Eq, Default, Clone)]
31pub struct SliceLossIndication {
32 pub sender_ssrc: u32,
34 pub media_ssrc: u32,
36
37 pub sli_entries: Vec<SliEntry>,
39}
40
41impl fmt::Display for SliceLossIndication {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(
44 f,
45 "SliceLossIndication {:x} {:x} {:?}",
46 self.sender_ssrc, self.media_ssrc, self.sli_entries,
47 )
48 }
49}
50
51impl Packet for SliceLossIndication {
52 fn header(&self) -> Header {
54 Header {
55 padding: get_padding_size(self.raw_size()) != 0,
56 count: FORMAT_SLI,
57 packet_type: PacketType::TransportSpecificFeedback,
58 length: ((self.marshal_size() / 4) - 1) as u16,
59 }
60 }
61
62 fn destination_ssrc(&self) -> Vec<u32> {
64 vec![self.media_ssrc]
65 }
66
67 fn raw_size(&self) -> usize {
68 HEADER_LENGTH + SLI_OFFSET + self.sli_entries.len() * 4
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::<SliceLossIndication>() == Some(self)
77 }
78
79 fn cloned(&self) -> Box<dyn Packet> {
80 Box::new(self.clone())
81 }
82}
83
84impl MarshalSize for SliceLossIndication {
85 fn marshal_size(&self) -> usize {
86 let l = self.raw_size();
87 l + get_padding_size(l)
89 }
90}
91
92impl Marshal for SliceLossIndication {
93 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
95 if (self.sli_entries.len() + SLI_LENGTH) as u8 > u8::MAX {
96 return Err(Error::TooManyReports);
97 }
98 if buf.remaining_mut() < self.marshal_size() {
99 return Err(Error::BufferTooShort);
100 }
101
102 let h = self.header();
103 let n = h.marshal_to(buf)?;
104 buf = &mut buf[n..];
105
106 buf.put_u32(self.sender_ssrc);
107 buf.put_u32(self.media_ssrc);
108
109 for s in &self.sli_entries {
110 let sli = ((s.first as u32 & 0x1FFF) << 19)
111 | ((s.number as u32 & 0x1FFF) << 6)
112 | (s.picture as u32 & 0x3F);
113
114 buf.put_u32(sli);
115 }
116
117 if h.padding {
118 put_padding(buf, self.raw_size());
119 }
120
121 Ok(self.marshal_size())
122 }
123}
124
125impl Unmarshal for SliceLossIndication {
126 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
128 where
129 Self: Sized,
130 B: Buf,
131 {
132 let raw_packet_len = raw_packet.remaining();
133 if raw_packet_len < (HEADER_LENGTH + SLI_OFFSET) {
134 return Err(Error::PacketTooShort);
135 }
136
137 let h = Header::unmarshal(raw_packet)?;
138
139 if raw_packet_len < (HEADER_LENGTH + (4 * h.length as usize)) {
140 return Err(Error::PacketTooShort);
141 }
142
143 if h.packet_type != PacketType::TransportSpecificFeedback || h.count != FORMAT_SLI {
144 return Err(Error::WrongType);
145 }
146
147 let sender_ssrc = raw_packet.get_u32();
148 let media_ssrc = raw_packet.get_u32();
149
150 let mut i = HEADER_LENGTH + SLI_OFFSET;
151 let mut sli_entries = vec![];
152 while i < HEADER_LENGTH + h.length as usize * 4 {
153 let sli = raw_packet.get_u32();
154 sli_entries.push(SliEntry {
155 first: ((sli >> 19) & 0x1FFF) as u16,
156 number: ((sli >> 6) & 0x1FFF) as u16,
157 picture: (sli & 0x3F) as u8,
158 });
159
160 i += 4;
161 }
162
163 if
164 raw_packet.has_remaining() {
166 raw_packet.advance(raw_packet.remaining());
167 }
168
169 Ok(SliceLossIndication {
170 sender_ssrc,
171 media_ssrc,
172 sli_entries,
173 })
174 }
175}