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    /// The lost slices being reported.
38    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    /// Header returns the Header associated with this packet.
53    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    /// destination_ssrc returns an array of SSRC values that this packet refers to.
63    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        // align to 32-bit boundary
88        l + get_padding_size(l)
89    }
90}
91
92impl Marshal for SliceLossIndication {
93    /// Marshal encodes the SliceLossIndication in binary
94    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    /// Unmarshal decodes the SliceLossIndication from binary
127    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        /*h.padding &&*/
165        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}