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