rtc_rtcp/
reception_report.rs

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