msf_rtp/rtcp/
report.rs

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