rtcp/reception_report.rs
1use std::any::Any;
2use std::fmt;
3
4use bytes::{Buf, BufMut};
5use util::marshal::{Marshal, MarshalSize, Unmarshal};
6
7use crate::error::Error;
8use crate::header::*;
9use crate::packet::*;
10use crate::util::*;
11
12pub(crate) const RECEPTION_REPORT_LENGTH: usize = 24;
13pub(crate) const FRACTION_LOST_OFFSET: usize = 4;
14pub(crate) const TOTAL_LOST_OFFSET: usize = 5;
15pub(crate) const LAST_SEQ_OFFSET: usize = 8;
16pub(crate) const JITTER_OFFSET: usize = 12;
17pub(crate) const LAST_SR_OFFSET: usize = 16;
18pub(crate) const DELAY_OFFSET: usize = 20;
19
20/// A ReceptionReport block conveys statistics on the reception of RTP packets
21/// from a single synchronization source.
22#[derive(Debug, PartialEq, Eq, Default, Clone)]
23pub struct ReceptionReport {
24 /// The SSRC identifier of the source to which the information in this
25 /// reception report block pertains.
26 pub ssrc: u32,
27 /// The fraction of RTP data packets from source SSRC lost since the
28 /// previous SR or RR packet was sent, expressed as a fixed point
29 /// number with the binary point at the left edge of the field.
30 pub fraction_lost: u8,
31 /// The total number of RTP data packets from source SSRC that have
32 /// been lost since the beginning of reception.
33 pub total_lost: u32,
34 /// The least significant 16 bits contain the highest sequence number received
35 /// in an RTP data packet from source SSRC, and the most significant 16 bits extend
36 /// that sequence number with the corresponding count of sequence number cycles.
37 pub last_sequence_number: u32,
38 /// An estimate of the statistical variance of the RTP data packet
39 /// interarrival time, measured in timestamp units and expressed as an
40 /// unsigned integer.
41 pub jitter: u32,
42 /// The middle 32 bits out of 64 in the NTP timestamp received as part of
43 /// the most recent RTCP sender report (SR) packet from source SSRC. If no
44 /// SR has been received yet, the field is set to zero.
45 pub last_sender_report: u32,
46 /// The delay, expressed in units of 1/65536 seconds, between receiving the
47 /// last SR packet from source SSRC and sending this reception report block.
48 /// If no SR packet has been received yet from SSRC, the field is set to zero.
49 pub delay: u32,
50}
51
52impl fmt::Display for ReceptionReport {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 write!(f, "{self:?}")
55 }
56}
57
58impl Packet for ReceptionReport {
59 fn header(&self) -> Header {
60 Header::default()
61 }
62
63 fn destination_ssrc(&self) -> Vec<u32> {
64 vec![]
65 }
66
67 fn raw_size(&self) -> usize {
68 RECEPTION_REPORT_LENGTH
69 }
70
71 fn as_any(&self) -> &(dyn Any + Send + Sync) {
72 self
73 }
74
75 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
76 other.as_any().downcast_ref::<ReceptionReport>() == Some(self)
77 }
78
79 fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
80 Box::new(self.clone())
81 }
82}
83
84impl MarshalSize for ReceptionReport {
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 ReceptionReport {
93 /// marshal_to encodes the ReceptionReport in binary
94 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> {
95 /*
96 * 0 1 2 3
97 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
98 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
99 * | SSRC |
100 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 * | fraction lost | cumulative number of packets lost |
102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 * | extended highest sequence number received |
104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 * | interarrival jitter |
106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 * | last SR (LSR) |
108 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 * | delay since last SR (DLSR) |
110 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
111 */
112 if buf.remaining_mut() < self.marshal_size() {
113 return Err(Error::BufferTooShort.into());
114 }
115
116 buf.put_u32(self.ssrc);
117
118 buf.put_u8(self.fraction_lost);
119
120 // pack TotalLost into 24 bits
121 if self.total_lost >= (1 << 25) {
122 return Err(Error::InvalidTotalLost.into());
123 }
124
125 buf.put_u8(((self.total_lost >> 16) & 0xFF) as u8);
126 buf.put_u8(((self.total_lost >> 8) & 0xFF) as u8);
127 buf.put_u8((self.total_lost & 0xFF) as u8);
128
129 buf.put_u32(self.last_sequence_number);
130 buf.put_u32(self.jitter);
131 buf.put_u32(self.last_sender_report);
132 buf.put_u32(self.delay);
133
134 put_padding(buf, self.raw_size());
135
136 Ok(self.marshal_size())
137 }
138}
139
140impl Unmarshal for ReceptionReport {
141 /// unmarshal decodes the ReceptionReport from binary
142 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error>
143 where
144 Self: Sized,
145 B: Buf,
146 {
147 let raw_packet_len = raw_packet.remaining();
148 if raw_packet_len < RECEPTION_REPORT_LENGTH {
149 return Err(Error::PacketTooShort.into());
150 }
151
152 /*
153 * 0 1 2 3
154 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
155 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
156 * | SSRC |
157 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 * | fraction lost | cumulative number of packets lost |
159 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 * | extended highest sequence number received |
161 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 * | interarrival jitter |
163 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 * | last SR (LSR) |
165 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 * | delay since last SR (DLSR) |
167 * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
168 */
169 let ssrc = raw_packet.get_u32();
170 let fraction_lost = raw_packet.get_u8();
171
172 let t0 = raw_packet.get_u8();
173 let t1 = raw_packet.get_u8();
174 let t2 = raw_packet.get_u8();
175 // TODO: The type of `total_lost` should be `i32`, per the RFC:
176 // The total number of RTP data packets from source SSRC_n that have
177 // been lost since the beginning of reception. This number is
178 // defined to be the number of packets expected less the number of
179 // packets actually received, where the number of packets received
180 // includes any which are late or duplicates. Thus, packets that
181 // arrive late are not counted as lost, and the loss may be negative
182 // if there are duplicates. The number of packets expected is
183 // defined to be the extended last sequence number received, as
184 // defined next, less the initial sequence number received. This may
185 // be calculated as shown in Appendix A.3.
186 let total_lost = (t2 as u32) | (t1 as u32) << 8 | (t0 as u32) << 16;
187
188 let last_sequence_number = raw_packet.get_u32();
189 let jitter = raw_packet.get_u32();
190 let last_sender_report = raw_packet.get_u32();
191 let delay = raw_packet.get_u32();
192
193 Ok(ReceptionReport {
194 ssrc,
195 fraction_lost,
196 total_lost,
197 last_sequence_number,
198 jitter,
199 last_sender_report,
200 delay,
201 })
202 }
203}