Skip to main content

rtc_rtcp/payload_feedbacks/slice_loss_indication/
mod.rs

1#[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/// SLIEntry represents a single entry to the SLI packet's
18/// list of lost slices.
19#[derive(Debug, PartialEq, Eq, Default, Clone)]
20pub struct SliEntry {
21    /// ID of first lost slice
22    pub first: u16,
23    /// Number of lost slices
24    pub number: u16,
25    /// ID of related picture
26    pub picture: u8,
27}
28
29/// The SliceLossIndication packet informs the encoder about the loss of a picture slice
30#[derive(Debug, PartialEq, Eq, Default, Clone)]
31pub struct SliceLossIndication {
32    /// SSRC of sender
33    pub sender_ssrc: u32,
34    /// SSRC of the media source
35    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    /// Header returns the Header associated with this packet.
52    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    /// destination_ssrc returns an array of SSRC values that this packet refers to.
62    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        // align to 32-bit boundary
87        l + get_padding_size(l)
88    }
89}
90
91impl Marshal for SliceLossIndication {
92    /// Marshal encodes the SliceLossIndication in binary
93    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    /// Unmarshal decodes the SliceLossIndication from binary
126    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        /*h.padding &&*/
164        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}