1 #[cfg(test)]
2 mod slice_loss_indication_test;
3 
4 use crate::{error::Error, header::*, packet::*, util::*};
5 use util::marshal::{Marshal, MarshalSize, Unmarshal};
6 
7 use bytes::{Buf, BufMut};
8 use std::any::Any;
9 use std::fmt;
10 
11 type Result<T> = std::result::Result<T, util::Error>;
12 
13 const SLI_LENGTH: usize = 2;
14 const SLI_OFFSET: usize = 8;
15 
16 /// SLIEntry represents a single entry to the SLI packet's
17 /// list of lost slices.
18 #[derive(Debug, PartialEq, Eq, Default, Clone)]
19 pub struct SliEntry {
20     /// ID of first lost slice
21     pub first: u16,
22     /// Number of lost slices
23     pub number: u16,
24     /// ID of related picture
25     pub picture: u8,
26 }
27 
28 /// The SliceLossIndication packet informs the encoder about the loss of a picture slice
29 #[derive(Debug, PartialEq, Eq, Default, Clone)]
30 pub struct SliceLossIndication {
31     /// SSRC of sender
32     pub sender_ssrc: u32,
33     /// SSRC of the media source
34     pub media_ssrc: u32,
35 
36     pub sli_entries: Vec<SliEntry>,
37 }
38 
39 impl fmt::Display for SliceLossIndication {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result40     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41         write!(
42             f,
43             "SliceLossIndication {:x} {:x} {:?}",
44             self.sender_ssrc, self.media_ssrc, self.sli_entries,
45         )
46     }
47 }
48 
49 impl Packet for SliceLossIndication {
50     /// Header returns the Header associated with this packet.
header(&self) -> Header51     fn header(&self) -> Header {
52         Header {
53             padding: get_padding_size(self.raw_size()) != 0,
54             count: FORMAT_SLI,
55             packet_type: PacketType::TransportSpecificFeedback,
56             length: ((self.marshal_size() / 4) - 1) as u16,
57         }
58     }
59 
60     /// destination_ssrc returns an array of SSRC values that this packet refers to.
destination_ssrc(&self) -> Vec<u32>61     fn destination_ssrc(&self) -> Vec<u32> {
62         vec![self.media_ssrc]
63     }
64 
raw_size(&self) -> usize65     fn raw_size(&self) -> usize {
66         HEADER_LENGTH + SLI_OFFSET + self.sli_entries.len() * 4
67     }
68 
as_any(&self) -> &(dyn Any + Send + Sync)69     fn as_any(&self) -> &(dyn Any + Send + Sync) {
70         self
71     }
72 
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool73     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
74         other
75             .as_any()
76             .downcast_ref::<SliceLossIndication>()
77             .map_or(false, |a| self == a)
78     }
79 
cloned(&self) -> Box<dyn Packet + Send + Sync>80     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
81         Box::new(self.clone())
82     }
83 }
84 
85 impl MarshalSize for SliceLossIndication {
marshal_size(&self) -> usize86     fn marshal_size(&self) -> usize {
87         let l = self.raw_size();
88         // align to 32-bit boundary
89         l + get_padding_size(l)
90     }
91 }
92 
93 impl Marshal for SliceLossIndication {
94     /// Marshal encodes the SliceLossIndication in binary
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>95     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
96         if (self.sli_entries.len() + SLI_LENGTH) as u8 > std::u8::MAX {
97             return Err(Error::TooManyReports.into());
98         }
99         if buf.remaining_mut() < self.marshal_size() {
100             return Err(Error::BufferTooShort.into());
101         }
102 
103         let h = self.header();
104         let n = h.marshal_to(buf)?;
105         buf = &mut buf[n..];
106 
107         buf.put_u32(self.sender_ssrc);
108         buf.put_u32(self.media_ssrc);
109 
110         for s in &self.sli_entries {
111             let sli = ((s.first as u32 & 0x1FFF) << 19)
112                 | ((s.number as u32 & 0x1FFF) << 6)
113                 | (s.picture as u32 & 0x3F);
114 
115             buf.put_u32(sli);
116         }
117 
118         if h.padding {
119             put_padding(buf, self.raw_size());
120         }
121 
122         Ok(self.marshal_size())
123     }
124 }
125 
126 impl Unmarshal for SliceLossIndication {
127     /// Unmarshal decodes the SliceLossIndication from binary
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,128     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
129     where
130         Self: Sized,
131         B: Buf,
132     {
133         let raw_packet_len = raw_packet.remaining();
134         if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
135             return Err(Error::PacketTooShort.into());
136         }
137 
138         let h = Header::unmarshal(raw_packet)?;
139 
140         if raw_packet_len < (HEADER_LENGTH + (4 * h.length as usize)) {
141             return Err(Error::PacketTooShort.into());
142         }
143 
144         if h.packet_type != PacketType::TransportSpecificFeedback || h.count != FORMAT_SLI {
145             return Err(Error::WrongType.into());
146         }
147 
148         let sender_ssrc = raw_packet.get_u32();
149         let media_ssrc = raw_packet.get_u32();
150 
151         let mut i = HEADER_LENGTH + SLI_OFFSET;
152         let mut sli_entries = vec![];
153         while i < HEADER_LENGTH + h.length as usize * 4 {
154             let sli = raw_packet.get_u32();
155             sli_entries.push(SliEntry {
156                 first: ((sli >> 19) & 0x1FFF) as u16,
157                 number: ((sli >> 6) & 0x1FFF) as u16,
158                 picture: (sli & 0x3F) as u8,
159             });
160 
161             i += 4;
162         }
163 
164         if
165         /*h.padding &&*/
166         raw_packet.has_remaining() {
167             raw_packet.advance(raw_packet.remaining());
168         }
169 
170         Ok(SliceLossIndication {
171             sender_ssrc,
172             media_ssrc,
173             sli_entries,
174         })
175     }
176 }
177