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>,
38}
39
40impl fmt::Display for SliceLossIndication {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(
43 f,
44 "SliceLossIndication {:x} {:x} {:?}",
45 self.sender_ssrc, self.media_ssrc, self.sli_entries,
46 )
47 }
48}
49
50impl Packet for SliceLossIndication {
51 fn header(&self) -> Header {
53 Header {
54 padding: get_padding_size(self.raw_size()) != 0,
55 count: FORMAT_SLI,
56 packet_type: PacketType::TransportSpecificFeedback,
57 length: ((self.marshal_size() / 4) - 1) as u16,
58 }
59 }
60
61 fn destination_ssrc(&self) -> Vec<u32> {
63 vec![self.media_ssrc]
64 }
65
66 fn raw_size(&self) -> usize {
67 HEADER_LENGTH + SLI_OFFSET + self.sli_entries.len() * 4
68 }
69
70 fn as_any(&self) -> &dyn Any {
71 self
72 }
73
74 fn equal(&self, other: &dyn Packet) -> bool {
75 other.as_any().downcast_ref::<SliceLossIndication>() == Some(self)
76 }
77
78 fn cloned(&self) -> Box<dyn Packet> {
79 Box::new(self.clone())
80 }
81}
82
83impl MarshalSize for SliceLossIndication {
84 fn marshal_size(&self) -> usize {
85 let l = self.raw_size();
86 l + get_padding_size(l)
88 }
89}
90
91impl Marshal for SliceLossIndication {
92 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
94 if (self.sli_entries.len() + SLI_LENGTH) as u8 > u8::MAX {
95 return Err(Error::TooManyReports);
96 }
97 if buf.remaining_mut() < self.marshal_size() {
98 return Err(Error::BufferTooShort);
99 }
100
101 let h = self.header();
102 let n = h.marshal_to(buf)?;
103 buf = &mut buf[n..];
104
105 buf.put_u32(self.sender_ssrc);
106 buf.put_u32(self.media_ssrc);
107
108 for s in &self.sli_entries {
109 let sli = ((s.first as u32 & 0x1FFF) << 19)
110 | ((s.number as u32 & 0x1FFF) << 6)
111 | (s.picture as u32 & 0x3F);
112
113 buf.put_u32(sli);
114 }
115
116 if h.padding {
117 put_padding(buf, self.raw_size());
118 }
119
120 Ok(self.marshal_size())
121 }
122}
123
124impl Unmarshal for SliceLossIndication {
125 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
127 where
128 Self: Sized,
129 B: Buf,
130 {
131 let raw_packet_len = raw_packet.remaining();
132 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
133 return Err(Error::PacketTooShort);
134 }
135
136 let h = Header::unmarshal(raw_packet)?;
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::TransportSpecificFeedback || h.count != FORMAT_SLI {
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 + SLI_OFFSET;
150 let mut sli_entries = vec![];
151 while i < HEADER_LENGTH + h.length as usize * 4 {
152 let sli = raw_packet.get_u32();
153 sli_entries.push(SliEntry {
154 first: ((sli >> 19) & 0x1FFF) as u16,
155 number: ((sli >> 6) & 0x1FFF) as u16,
156 picture: (sli & 0x3F) as u8,
157 });
158
159 i += 4;
160 }
161
162 if
163 raw_packet.has_remaining() {
165 raw_packet.advance(raw_packet.remaining());
166 }
167
168 Ok(SliceLossIndication {
169 sender_ssrc,
170 media_ssrc,
171 sli_entries,
172 })
173 }
174}