xref: /webrtc/rtcp/src/reception_report.rs (revision 259fddd2)
1 use std::io::{Read, Write};
2 
3 use util::Error;
4 
5 use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6 
7 use super::errors::*;
8 
9 // A ReceptionReport block conveys statistics on the reception of RTP packets
10 // from a single synchronization source.
11 #[derive(Debug, PartialEq, Default, Clone)]
12 pub struct ReceptionReport {
13     // The SSRC identifier of the source to which the information in this
14     // reception report block pertains.
15     pub ssrc: u32,
16     // The fraction of RTP data packets from source SSRC lost since the
17     // previous SR or RR packet was sent, expressed as a fixed point
18     // number with the binary point at the left edge of the field.
19     pub fraction_lost: u8,
20     // The total number of RTP data packets from source SSRC that have
21     // been lost since the beginning of reception.
22     pub total_lost: u32,
23     // The low 16 bits contain the highest sequence number received in an
24     // RTP data packet from source SSRC, and the most significant 16
25     // bits extend that sequence number with the corresponding count of
26     // sequence number cycles.
27     pub last_sequence_number: u32,
28     // An estimate of the statistical variance of the RTP data packet
29     // interarrival time, measured in timestamp units and expressed as an
30     // unsigned integer.
31     pub jitter: u32,
32     // The middle 32 bits out of 64 in the NTP timestamp received as part of
33     // the most recent RTCP sender report (SR) packet from source SSRC. If no
34     // SR has been received yet, the field is set to zero.
35     pub last_sender_report: u32,
36     // The delay, expressed in units of 1/65536 seconds, between receiving the
37     // last SR packet from source SSRC and sending this reception report block.
38     // If no SR packet has been received yet from SSRC, the field is set to zero.
39     pub delay: u32,
40 }
41 
42 const RECEPTION_REPORT_LENGTH: usize = 24;
43 /*const fractionLostOffset: u8 = 4;
44 const totalLostOffset: u8 = 5;
45 const lastSeqOffset: u8 = 8;
46 const jitterOffset: u8 = 12;
47 const lastSROffset: u8 = 16;
48 const delayOffset: u8 = 20;*/
49 
50 impl ReceptionReport {
51     pub fn size(&self) -> usize {
52         RECEPTION_REPORT_LENGTH
53     }
54 
55     // Marshal encodes the ReceptionReport in binary
56     pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
57         /*
58          *  0                   1                   2                   3
59          *  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
60          * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
61          * |                              SSRC                             |
62          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63          * | fraction lost |       cumulative number of packets lost       |
64          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65          * |           extended highest sequence number received           |
66          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67          * |                      interarrival jitter                      |
68          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69          * |                         last SR (LSR)                         |
70          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71          * |                   delay since last SR (DLSR)                  |
72          * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
73          */
74         writer.write_u32::<BigEndian>(self.ssrc)?;
75         writer.write_u8(self.fraction_lost)?;
76 
77         // pack TotalLost into 24 bits
78         if self.total_lost >= (1 << 25) {
79             return Err(ERR_INVALID_TOTAL_LOST.clone());
80         }
81         writer.write_u8(((self.total_lost >> 16) & 0xFF) as u8)?;
82         writer.write_u8(((self.total_lost >> 8) & 0xFF) as u8)?;
83         writer.write_u8(((self.total_lost) & 0xFF) as u8)?;
84 
85         writer.write_u32::<BigEndian>(self.last_sequence_number)?;
86         writer.write_u32::<BigEndian>(self.jitter)?;
87         writer.write_u32::<BigEndian>(self.last_sender_report)?;
88         writer.write_u32::<BigEndian>(self.delay)?;
89 
90         Ok(())
91     }
92 
93     // Unmarshal decodes the ReceptionReport from binary
94     pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self, 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 
113         let ssrc = reader.read_u32::<BigEndian>()?;
114         let fraction_lost = reader.read_u8()?;
115 
116         let b0 = reader.read_u8()?;
117         let b1 = reader.read_u8()?;
118         let b2 = reader.read_u8()?;
119         let total_lost = b2 as u32 | (b1 as u32) << 8 | (b0 as u32) << 16;
120 
121         let last_sequence_number = reader.read_u32::<BigEndian>()?;
122         let jitter = reader.read_u32::<BigEndian>()?;
123         let last_sender_report = reader.read_u32::<BigEndian>()?;
124         let delay = reader.read_u32::<BigEndian>()?;
125 
126         Ok(ReceptionReport {
127             ssrc,
128             fraction_lost,
129             total_lost,
130             last_sequence_number,
131             jitter,
132             last_sender_report,
133             delay,
134         })
135     }
136 }
137