Skip to main content

rtc_rtcp/payload_feedbacks/full_intra_request/
mod.rs

1#[cfg(test)]
2mod full_intra_request_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
14/// A FIREntry is a (ssrc, seqno) pair, as carried by FullIntraRequest.
15#[derive(Debug, PartialEq, Eq, Default, Clone)]
16pub struct FirEntry {
17    /// The SSRC being asked for an intra frame.
18    pub ssrc: u32,
19    /// A counter incremented per request, so a sender can ignore retransmitted duplicates.
20    pub sequence_number: u8,
21}
22
23/// The FullIntraRequest packet is used to reliably request an Intra frame
24/// in a video stream.  See RFC 5104 Section 3.5.1.  This is not for loss
25/// recovery, which should use PictureLossIndication (PLI) instead.
26#[derive(Debug, PartialEq, Eq, Default, Clone)]
27pub struct FullIntraRequest {
28    /// The SSRC of the requesting receiver.
29    pub sender_ssrc: u32,
30    /// The media source being addressed.
31    pub media_ssrc: u32,
32    /// One entry per SSRC an intra frame is requested from.
33    pub fir: Vec<FirEntry>,
34}
35
36const FIR_OFFSET: usize = 8;
37
38impl fmt::Display for FullIntraRequest {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        let mut out = format!("FullIntraRequest {} {}", self.sender_ssrc, self.media_ssrc);
41        for e in &self.fir {
42            out += format!(" ({} {})", e.ssrc, e.sequence_number).as_str();
43        }
44        write!(f, "{out}")
45    }
46}
47
48impl Packet for FullIntraRequest {
49    fn header(&self) -> Header {
50        Header {
51            padding: get_padding_size(self.raw_size()) != 0,
52            count: FORMAT_FIR,
53            packet_type: PacketType::PayloadSpecificFeedback,
54            length: ((self.marshal_size() / 4) - 1) as u16,
55        }
56    }
57
58    /// destination_ssrc returns an array of SSRC values that this packet refers to.
59    fn destination_ssrc(&self) -> Vec<u32> {
60        let mut ssrcs: Vec<u32> = Vec::with_capacity(self.fir.len());
61        for entry in &self.fir {
62            ssrcs.push(entry.ssrc);
63        }
64        ssrcs
65    }
66
67    fn raw_size(&self) -> usize {
68        HEADER_LENGTH + FIR_OFFSET + self.fir.len() * 8
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::<FullIntraRequest>() == Some(self)
77    }
78
79    fn cloned(&self) -> Box<dyn Packet> {
80        Box::new(self.clone())
81    }
82}
83
84impl MarshalSize for FullIntraRequest {
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 FullIntraRequest {
93    /// Marshal encodes the FullIntraRequest
94    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
95        if buf.remaining_mut() < self.marshal_size() {
96            return Err(Error::BufferTooShort);
97        }
98
99        let h = self.header();
100        let n = h.marshal_to(buf)?;
101        buf = &mut buf[n..];
102
103        buf.put_u32(self.sender_ssrc);
104        buf.put_u32(self.media_ssrc);
105
106        for fir in self.fir.iter() {
107            buf.put_u32(fir.ssrc);
108            buf.put_u8(fir.sequence_number);
109            buf.put_u8(0);
110            buf.put_u16(0);
111        }
112
113        if h.padding {
114            put_padding(buf, self.raw_size());
115        }
116
117        Ok(self.marshal_size())
118    }
119}
120
121impl Unmarshal for FullIntraRequest {
122    /// Unmarshal decodes the FullIntraRequest
123    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
124    where
125        Self: Sized,
126        B: Buf,
127    {
128        let raw_packet_len = raw_packet.remaining();
129        if raw_packet_len < FIR_MIN_OCTET_COUNT {
130            return Err(Error::PacketTooShort);
131        }
132
133        let h = Header::unmarshal(raw_packet)?;
134        if (HEADER_LENGTH + 4 * (h.length as usize)) < FIR_MIN_OCTET_COUNT {
135            return Err(Error::InvalidHeader);
136        }
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::PayloadSpecificFeedback || h.count != FORMAT_FIR {
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 + FIR_OFFSET;
150        let mut fir = vec![];
151        while i < HEADER_LENGTH + (h.length * 4) as usize {
152            // An FIR entry is 8 bytes
153            if raw_packet.remaining() < 8 {
154                return Err(Error::PacketTooShort);
155            }
156
157            fir.push(FirEntry {
158                ssrc: raw_packet.get_u32(),
159                sequence_number: raw_packet.get_u8(),
160            });
161            raw_packet.get_u8();
162            raw_packet.get_u16();
163
164            i += 8;
165        }
166
167        if
168        /*h.padding &&*/
169        raw_packet.has_remaining() {
170            raw_packet.advance(raw_packet.remaining());
171        }
172
173        Ok(FullIntraRequest {
174            sender_ssrc,
175            media_ssrc,
176            fir,
177        })
178    }
179}