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    pub ssrc: u32,
18    pub sequence_number: u8,
19}
20
21/// The FullIntraRequest packet is used to reliably request an Intra frame
22/// in a video stream.  See RFC 5104 Section 3.5.1.  This is not for loss
23/// recovery, which should use PictureLossIndication (PLI) instead.
24#[derive(Debug, PartialEq, Eq, Default, Clone)]
25pub struct FullIntraRequest {
26    pub sender_ssrc: u32,
27    pub media_ssrc: u32,
28    pub fir: Vec<FirEntry>,
29}
30
31const FIR_OFFSET: usize = 8;
32
33impl fmt::Display for FullIntraRequest {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        let mut out = format!("FullIntraRequest {} {}", self.sender_ssrc, self.media_ssrc);
36        for e in &self.fir {
37            out += format!(" ({} {})", e.ssrc, e.sequence_number).as_str();
38        }
39        write!(f, "{out}")
40    }
41}
42
43impl Packet for FullIntraRequest {
44    fn header(&self) -> Header {
45        Header {
46            padding: get_padding_size(self.raw_size()) != 0,
47            count: FORMAT_FIR,
48            packet_type: PacketType::PayloadSpecificFeedback,
49            length: ((self.marshal_size() / 4) - 1) as u16,
50        }
51    }
52
53    /// destination_ssrc returns an array of SSRC values that this packet refers to.
54    fn destination_ssrc(&self) -> Vec<u32> {
55        let mut ssrcs: Vec<u32> = Vec::with_capacity(self.fir.len());
56        for entry in &self.fir {
57            ssrcs.push(entry.ssrc);
58        }
59        ssrcs
60    }
61
62    fn raw_size(&self) -> usize {
63        HEADER_LENGTH + FIR_OFFSET + self.fir.len() * 8
64    }
65
66    fn as_any(&self) -> &dyn Any {
67        self
68    }
69
70    fn equal(&self, other: &dyn Packet) -> bool {
71        other.as_any().downcast_ref::<FullIntraRequest>() == Some(self)
72    }
73
74    fn cloned(&self) -> Box<dyn Packet> {
75        Box::new(self.clone())
76    }
77}
78
79impl MarshalSize for FullIntraRequest {
80    fn marshal_size(&self) -> usize {
81        let l = self.raw_size();
82        // align to 32-bit boundary
83        l + get_padding_size(l)
84    }
85}
86
87impl Marshal for FullIntraRequest {
88    /// Marshal encodes the FullIntraRequest
89    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
90        if buf.remaining_mut() < self.marshal_size() {
91            return Err(Error::BufferTooShort);
92        }
93
94        let h = self.header();
95        let n = h.marshal_to(buf)?;
96        buf = &mut buf[n..];
97
98        buf.put_u32(self.sender_ssrc);
99        buf.put_u32(self.media_ssrc);
100
101        for fir in self.fir.iter() {
102            buf.put_u32(fir.ssrc);
103            buf.put_u8(fir.sequence_number);
104            buf.put_u8(0);
105            buf.put_u16(0);
106        }
107
108        if h.padding {
109            put_padding(buf, self.raw_size());
110        }
111
112        Ok(self.marshal_size())
113    }
114}
115
116impl Unmarshal for FullIntraRequest {
117    /// Unmarshal decodes the FullIntraRequest
118    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
119    where
120        Self: Sized,
121        B: Buf,
122    {
123        let raw_packet_len = raw_packet.remaining();
124        if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
125            return Err(Error::PacketTooShort);
126        }
127
128        let h = Header::unmarshal(raw_packet)?;
129
130        if raw_packet_len < (HEADER_LENGTH + (4 * h.length) as usize) {
131            return Err(Error::PacketTooShort);
132        }
133
134        if h.packet_type != PacketType::PayloadSpecificFeedback || h.count != FORMAT_FIR {
135            return Err(Error::WrongType);
136        }
137
138        let sender_ssrc = raw_packet.get_u32();
139        let media_ssrc = raw_packet.get_u32();
140
141        let mut i = HEADER_LENGTH + FIR_OFFSET;
142        let mut fir = vec![];
143        while i < HEADER_LENGTH + (h.length * 4) as usize {
144            fir.push(FirEntry {
145                ssrc: raw_packet.get_u32(),
146                sequence_number: raw_packet.get_u8(),
147            });
148            raw_packet.get_u8();
149            raw_packet.get_u16();
150
151            i += 8;
152        }
153
154        if
155        /*h.padding &&*/
156        raw_packet.has_remaining() {
157            raw_packet.advance(raw_packet.remaining());
158        }
159
160        Ok(FullIntraRequest {
161            sender_ssrc,
162            media_ssrc,
163            fir,
164        })
165    }
166}