Skip to main content

msf_rtp/rtcp/
report.rs

1use std::time::Duration;
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use zerocopy::{
5    byteorder::network_endian::{U32, U64},
6    FromBytes, Immutable, IntoBytes, KnownLayout, SizeError, Unaligned,
7};
8
9use crate::{InvalidInput, RtcpPacket, RtcpPacketType};
10
11/// Helper struct.
12#[derive(Copy, Clone, KnownLayout, Immutable, Unaligned, IntoBytes, FromBytes)]
13#[repr(C)]
14struct RawReportBlock {
15    ssrc: U32,
16    loss: U32,
17    extended_sequence_number: U32,
18    jitter: U32,
19    last_sr_timestamp: U32,
20    delay_since_last_sr: U32,
21}
22
23/// Sender/receiver report block.
24#[derive(Copy, Clone)]
25pub struct ReportBlock {
26    ssrc: u32,
27    loss: u32,
28    extended_sequence_number: u32,
29    jitter: u32,
30    last_sr_timestamp: u32,
31    delay_since_last_sr: u32,
32}
33
34impl ReportBlock {
35    /// Size of an encoded report block.
36    pub const RAW_SIZE: usize = std::mem::size_of::<RawReportBlock>();
37
38    /// Create a new report block.
39    #[inline]
40    pub const fn new(ssrc: u32) -> Self {
41        Self {
42            ssrc,
43            loss: 0,
44            extended_sequence_number: 0,
45            jitter: 0,
46            last_sr_timestamp: 0,
47            delay_since_last_sr: 0,
48        }
49    }
50
51    /// Decode a report block from given data.
52    pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
53        let (raw, _) = RawReportBlock::ref_from_prefix(data)
54            .map_err(SizeError::from)
55            .map_err(|_| InvalidInput::new())?;
56
57        let res = Self {
58            ssrc: raw.ssrc.get(),
59            loss: raw.loss.get(),
60            extended_sequence_number: raw.extended_sequence_number.get(),
61            jitter: raw.jitter.get(),
62            last_sr_timestamp: raw.last_sr_timestamp.get(),
63            delay_since_last_sr: raw.delay_since_last_sr.get(),
64        };
65
66        data.advance(std::mem::size_of::<RawReportBlock>());
67
68        Ok(res)
69    }
70
71    /// Encode the report block.
72    pub fn encode(&self, buf: &mut BytesMut) {
73        let raw = RawReportBlock {
74            ssrc: U32::new(self.ssrc),
75            loss: U32::new(self.loss),
76            extended_sequence_number: U32::new(self.extended_sequence_number),
77            jitter: U32::new(self.jitter),
78            last_sr_timestamp: U32::new(self.last_sr_timestamp),
79            delay_since_last_sr: U32::new(self.delay_since_last_sr),
80        };
81
82        buf.extend_from_slice(raw.as_bytes());
83    }
84
85    /// Get SSRC.
86    #[inline]
87    pub fn ssrc(&self) -> u32 {
88        self.ssrc
89    }
90
91    /// Set SSRC.
92    #[inline]
93    pub fn with_ssrc(mut self, ssrc: u32) -> Self {
94        self.ssrc = ssrc;
95        self
96    }
97
98    /// Get fractional loss as 0.8 fixed point number.
99    #[inline]
100    pub fn fractional_loss(&self) -> u8 {
101        (self.loss >> 24) as u8
102    }
103
104    /// Set fractional loss as 0.8 fixed point number.
105    #[inline]
106    pub fn with_fractional_loss(mut self, loss: u8) -> Self {
107        self.loss &= 0x00ffffff;
108        self.loss |= (loss as u32) << 24;
109        self
110    }
111
112    /// Get cumulative packet loss (the precision is only up to 24 bits).
113    #[inline]
114    pub fn cumulative_loss(&self) -> i32 {
115        ((self.loss << 8) as i32) >> 8
116    }
117
118    /// Set cumulative packet loss (the precision is only up to 24 bits).
119    #[inline]
120    pub fn with_cumulative_loss(mut self, loss: i32) -> Self {
121        let min = -(1i32 << 23);
122        let max = (1i32 << 23) - 1;
123
124        let loss = loss.clamp(min, max) as u32;
125
126        self.loss &= 0xff000000;
127        self.loss |= loss & 0x00ffffff;
128        self
129    }
130
131    /// Set loss calculated from a given number of expected packets vs. a given
132    /// number of received packets.
133    pub fn with_loss(self, expected: u64, received: u64) -> Self {
134        let delta = expected as i64 - received as i64;
135
136        let fraction = if delta < 0 {
137            0
138        } else {
139            ((delta as u64) << 8) / expected
140        };
141
142        self.with_fractional_loss(fraction as u8)
143            .with_cumulative_loss(delta as i32)
144    }
145
146    /// Get extended highest sequence number.
147    #[inline]
148    pub fn extended_sequence_number(&self) -> u32 {
149        self.extended_sequence_number
150    }
151
152    /// Set the extended sequence number.
153    #[inline]
154    pub fn with_extended_sequence_number(mut self, n: u32) -> Self {
155        self.extended_sequence_number = n;
156        self
157    }
158
159    /// Get jitter.
160    #[inline]
161    pub fn jitter(&self) -> u32 {
162        self.jitter
163    }
164
165    /// Set the jitter.
166    #[inline]
167    pub fn with_jitter(mut self, jitter: u32) -> Self {
168        self.jitter = jitter;
169        self
170    }
171
172    /// Get NTP timestamp of the last sender report (after truncating to the
173    /// middle 32 bits).
174    ///
175    /// The returned timestamp is a 32.32 fixed point number.
176    #[inline]
177    pub fn last_sr_timestamp(&self) -> u64 {
178        (self.last_sr_timestamp as u64) << 16
179    }
180
181    /// Set NTP timestamp of the last sender report.
182    ///
183    /// The timestamp is expected to be a 32.32 fixed point number and it will
184    /// be truncated to the middle 32 bits.
185    #[inline]
186    pub fn with_last_sr_timestamp(mut self, ts: u64) -> Self {
187        self.last_sr_timestamp = (ts >> 16) as u32;
188        self
189    }
190
191    /// Get delay since the last sender report.
192    #[inline]
193    pub fn delay_since_last_sr(&self) -> Duration {
194        let secs = (self.delay_since_last_sr >> 16) as u64;
195        let nanos = ((self.delay_since_last_sr & 0xffff) as u64 * 1_000_000_000) >> 16;
196
197        Duration::new(secs, nanos as u32)
198    }
199
200    /// Set delay since the last sender report.
201    #[inline]
202    pub fn with_delay_since_last_sr(mut self, delay: Duration) -> Self {
203        let secs = (delay.as_secs() << 16) as u32;
204        let fraction = (((delay.subsec_nanos() as u64) << 16) / 1_000_000_000) as u32;
205
206        self.delay_since_last_sr = secs + fraction;
207        self
208    }
209
210    /// Get size of the encoded report block.
211    #[inline]
212    pub fn raw_size(&self) -> usize {
213        Self::RAW_SIZE
214    }
215}
216
217/// Helper struct.
218#[derive(Copy, Clone, KnownLayout, Immutable, Unaligned, IntoBytes, FromBytes)]
219#[repr(C)]
220struct RawSenderReportHeader {
221    sender_ssrc: U32,
222    ntp_timestamp: U64,
223    rtp_timestamp: U32,
224    packet_count: U32,
225    octet_count: U32,
226}
227
228/// Sender report.
229#[derive(Clone)]
230pub struct SenderReport {
231    sender_ssrc: u32,
232    ntp_timestamp: u64,
233    rtp_timestamp: u32,
234    packet_count: u32,
235    octet_count: u32,
236    report_blocks: Vec<ReportBlock>,
237}
238
239impl SenderReport {
240    /// Create a new sender report.
241    #[inline]
242    pub const fn new(sender_ssrc: u32) -> Self {
243        Self {
244            sender_ssrc,
245            ntp_timestamp: 0,
246            rtp_timestamp: 0,
247            packet_count: 0,
248            octet_count: 0,
249            report_blocks: Vec::new(),
250        }
251    }
252
253    /// Decode sender report.
254    pub fn decode(packet: &RtcpPacket) -> Result<Self, InvalidInput> {
255        let header = packet.header();
256
257        let mut data = packet.stripped_payload();
258
259        let (raw, _) = RawSenderReportHeader::ref_from_prefix(&data)
260            .map_err(SizeError::from)
261            .map_err(|_| InvalidInput::new())?;
262
263        let mut res = Self {
264            sender_ssrc: raw.sender_ssrc.get(),
265            ntp_timestamp: raw.ntp_timestamp.get(),
266            rtp_timestamp: raw.rtp_timestamp.get(),
267            packet_count: raw.packet_count.get(),
268            octet_count: raw.octet_count.get(),
269            report_blocks: Vec::with_capacity(header.item_count() as usize),
270        };
271
272        data.advance(std::mem::size_of::<RawSenderReportHeader>());
273
274        for _ in 0..header.item_count() {
275            res.report_blocks.push(ReportBlock::decode(&mut data)?);
276        }
277
278        Ok(res)
279    }
280
281    /// Encode the sender report.
282    pub fn encode(&self) -> RtcpPacket {
283        let mut payload = BytesMut::with_capacity(self.raw_size());
284
285        let raw = RawSenderReportHeader {
286            sender_ssrc: U32::new(self.sender_ssrc),
287            ntp_timestamp: U64::new(self.ntp_timestamp),
288            rtp_timestamp: U32::new(self.rtp_timestamp),
289            packet_count: U32::new(self.packet_count),
290            octet_count: U32::new(self.octet_count),
291        };
292
293        payload.extend_from_slice(raw.as_bytes());
294
295        for block in &self.report_blocks {
296            block.encode(&mut payload);
297        }
298
299        RtcpPacket::new(RtcpPacketType::SR)
300            .with_item_count(self.report_blocks.len() as u8)
301            .with_payload(payload.freeze(), 0)
302    }
303
304    /// Get SSRC identifier of the sender.
305    #[inline]
306    pub fn sender_ssrc(&self) -> u32 {
307        self.sender_ssrc
308    }
309
310    /// Set the SSRC identifier of the sender.
311    #[inline]
312    pub fn with_sender_ssrc(mut self, ssrc: u32) -> Self {
313        self.sender_ssrc = ssrc;
314        self
315    }
316
317    /// Get NTP timestamp as a 32.32 fixed point number.
318    #[inline]
319    pub fn ntp_timestamp(&self) -> u64 {
320        self.ntp_timestamp
321    }
322
323    /// Set the NTP timestamp as a 32.32. fixed point number.
324    #[inline]
325    pub fn with_ntp_timestamp(mut self, timestamp: u64) -> Self {
326        self.ntp_timestamp = timestamp;
327        self
328    }
329
330    /// Get RTP timestamp.
331    #[inline]
332    pub fn rtp_timestamp(&self) -> u32 {
333        self.rtp_timestamp
334    }
335
336    /// Set the RTP timestamp.
337    #[inline]
338    pub fn with_rtp_timestamp(mut self, timestamp: u32) -> Self {
339        self.rtp_timestamp = timestamp;
340        self
341    }
342
343    /// Get packet count.
344    #[inline]
345    pub fn packet_count(&self) -> u32 {
346        self.packet_count
347    }
348
349    /// Set the packet count.
350    #[inline]
351    pub fn with_packet_count(mut self, count: u32) -> Self {
352        self.packet_count = count;
353        self
354    }
355
356    /// Get octet count.
357    #[inline]
358    pub fn octet_count(&self) -> u32 {
359        self.octet_count
360    }
361
362    /// Set the octet count.
363    #[inline]
364    pub fn with_octet_count(mut self, count: u32) -> Self {
365        self.octet_count = count;
366        self
367    }
368
369    /// Get report blocks.
370    #[inline]
371    pub fn report_blocks(&self) -> &[ReportBlock] {
372        &self.report_blocks
373    }
374
375    /// Set the report blocks.
376    ///
377    /// # Panics
378    /// The method will panic if the number of report blocks is greater than
379    /// 31.
380    #[inline]
381    pub fn with_report_blocks<T>(mut self, blocks: T) -> Self
382    where
383        T: Into<Vec<ReportBlock>>,
384    {
385        let blocks = blocks.into();
386
387        assert!(blocks.len() < 32);
388
389        self.report_blocks = blocks;
390        self
391    }
392
393    /// Get size of the encoded sender report.
394    #[inline]
395    pub fn raw_size(&self) -> usize {
396        std::mem::size_of::<RawSenderReportHeader>()
397            + std::mem::size_of::<RawReportBlock>() * self.report_blocks.len()
398    }
399}
400
401/// Receiver report.
402#[derive(Clone)]
403pub struct ReceiverReport {
404    sender_ssrc: u32,
405    report_blocks: Vec<ReportBlock>,
406}
407
408impl ReceiverReport {
409    /// Create a new receiver report.
410    #[inline]
411    pub const fn new(sender_ssrc: u32) -> Self {
412        Self {
413            sender_ssrc,
414            report_blocks: Vec::new(),
415        }
416    }
417
418    /// Decode receiver report.
419    pub fn decode(packet: &RtcpPacket) -> Result<Self, InvalidInput> {
420        let header = packet.header();
421
422        let mut data = packet.stripped_payload();
423
424        if data.len() < 4 {
425            return Err(InvalidInput::new());
426        }
427
428        let mut res = Self {
429            sender_ssrc: data.get_u32(),
430            report_blocks: Vec::with_capacity(header.item_count() as usize),
431        };
432
433        for _ in 0..header.item_count() {
434            res.report_blocks.push(ReportBlock::decode(&mut data)?);
435        }
436
437        Ok(res)
438    }
439
440    /// Encode the sender report.
441    pub fn encode(&self) -> RtcpPacket {
442        let mut payload = BytesMut::with_capacity(self.raw_size());
443
444        payload.put_u32(self.sender_ssrc);
445
446        for block in &self.report_blocks {
447            block.encode(&mut payload);
448        }
449
450        RtcpPacket::new(RtcpPacketType::RR)
451            .with_item_count(self.report_blocks.len() as u8)
452            .with_payload(payload.freeze(), 0)
453    }
454
455    /// Get SSRC identifier of the sender.
456    #[inline]
457    pub fn sender_ssrc(&self) -> u32 {
458        self.sender_ssrc
459    }
460
461    /// Set the SSRC identifier of the sender.
462    #[inline]
463    pub fn with_sender_ssrc(mut self, ssrc: u32) -> Self {
464        self.sender_ssrc = ssrc;
465        self
466    }
467
468    /// Get report blocks.
469    #[inline]
470    pub fn report_blocks(&self) -> &[ReportBlock] {
471        &self.report_blocks
472    }
473
474    /// Set the report blocks.
475    ///
476    /// # Panics
477    /// The method will panic if the number of report blocks is greater than
478    /// 31.
479    #[inline]
480    pub fn with_report_blocks<T>(mut self, blocks: T) -> Self
481    where
482        T: Into<Vec<ReportBlock>>,
483    {
484        let blocks = blocks.into();
485
486        assert!(blocks.len() < 32);
487
488        self.report_blocks = blocks;
489        self
490    }
491
492    /// Get size of the encoded sender report.
493    #[inline]
494    pub fn raw_size(&self) -> usize {
495        4 + std::mem::size_of::<RawReportBlock>() * self.report_blocks.len()
496    }
497}