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(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    /// Create a new report block.
31    #[inline]
32    pub const fn new() -> Self {
33        Self {
34            ssrc: 0,
35            loss: 0,
36            extended_sequence_number: 0,
37            jitter: 0,
38            last_sr_timestamp: 0,
39            delay_since_last_sr: 0,
40        }
41    }
42
43    /// Decode a report block from given data.
44    pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
45        if data.len() < std::mem::size_of::<RawReportBlock>() {
46            return Err(InvalidInput);
47        }
48
49        let ptr = data.as_ptr() as *const RawReportBlock;
50        let raw = unsafe { &*ptr };
51
52        let res = Self {
53            ssrc: u32::from_be(raw.ssrc),
54            loss: u32::from_be(raw.loss),
55            extended_sequence_number: u32::from_be(raw.extended_sequence_number),
56            jitter: u32::from_be(raw.jitter),
57            last_sr_timestamp: u32::from_be(raw.last_sr_timestamp),
58            delay_since_last_sr: u32::from_be(raw.delay_since_last_sr),
59        };
60
61        data.advance(std::mem::size_of::<RawReportBlock>());
62
63        Ok(res)
64    }
65
66    /// Encode the report block.
67    pub fn encode(&self, buf: &mut BytesMut) {
68        let raw = RawReportBlock {
69            ssrc: self.ssrc.to_be(),
70            loss: self.loss.to_be(),
71            extended_sequence_number: self.extended_sequence_number.to_be(),
72            jitter: self.jitter.to_be(),
73            last_sr_timestamp: self.last_sr_timestamp.to_be(),
74            delay_since_last_sr: self.delay_since_last_sr.to_be(),
75        };
76
77        let ptr = &raw as *const _ as *const u8;
78
79        let data =
80            unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawReportBlock>()) };
81
82        buf.extend_from_slice(data);
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.max(min).min(max) as u32;
125
126        self.loss &= 0xff000000;
127        self.loss |= loss & 0x00ffffff;
128        self
129    }
130
131    /// Get extended highest sequence number.
132    #[inline]
133    pub fn extended_sequence_number(&self) -> u32 {
134        self.extended_sequence_number
135    }
136
137    /// Set the extended sequence number.
138    #[inline]
139    pub fn with_extended_sequence_number(mut self, n: u32) -> Self {
140        self.extended_sequence_number = n;
141        self
142    }
143
144    /// Get jitter.
145    #[inline]
146    pub fn jitter(&self) -> u32 {
147        self.jitter
148    }
149
150    /// Set the jitter.
151    #[inline]
152    pub fn with_jitter(mut self, jitter: u32) -> Self {
153        self.jitter = jitter;
154        self
155    }
156
157    /// Get NTP timestamp of the last sender report (after truncating to the
158    /// middle 32 bits).
159    ///
160    /// The returned timestamp is a 32.32 fixed point number.
161    #[inline]
162    pub fn last_sr_timestamp(&self) -> u64 {
163        (self.last_sr_timestamp as u64) << 16
164    }
165
166    /// Set NTP timestamp of the last sender report.
167    ///
168    /// The timestamp is expected to be a 32.32 fixed point number and it will
169    /// be truncated to the middle 32 bits.
170    #[inline]
171    pub fn with_last_sr_timestamp(mut self, ts: u64) -> Self {
172        self.last_sr_timestamp = (ts >> 16) as u32;
173        self
174    }
175
176    /// Get delay since the last sender report.
177    #[inline]
178    pub fn delay_since_last_sr(&self) -> Duration {
179        let secs = (self.delay_since_last_sr >> 16) as u64;
180        let nanos = ((self.delay_since_last_sr & 0xffff) as u64 * 1_000_000_000) >> 16;
181
182        Duration::new(secs, nanos as u32)
183    }
184
185    /// Set delay since the last sender report.
186    #[inline]
187    pub fn with_delay_since_last_sr(mut self, delay: Duration) -> Self {
188        let secs = (delay.as_secs() << 16) as u32;
189        let fraction = (((delay.subsec_nanos() as u64) << 16) / 1_000_000_000) as u32;
190
191        self.delay_since_last_sr = secs + fraction;
192        self
193    }
194
195    /// Get size of the encoded report block.
196    #[inline]
197    pub fn raw_size(&self) -> usize {
198        std::mem::size_of::<RawReportBlock>()
199    }
200}
201
202impl Default for ReportBlock {
203    #[inline]
204    fn default() -> Self {
205        Self::new()
206    }
207}
208
209/// Helper struct.
210#[repr(packed)]
211struct RawSenderReportHeader {
212    ssrc: u32,
213    ntp_timestamp: u64,
214    rtp_timestamp: u32,
215    packet_count: u32,
216    octet_count: u32,
217}
218
219/// Sender report.
220#[derive(Clone)]
221pub struct SenderReport {
222    ssrc: u32,
223    ntp_timestamp: u64,
224    rtp_timestamp: u32,
225    packet_count: u32,
226    octet_count: u32,
227    blocks: Vec<ReportBlock>,
228}
229
230impl SenderReport {
231    /// Create a new sender report.
232    #[inline]
233    pub const fn new() -> Self {
234        Self {
235            ssrc: 0,
236            ntp_timestamp: 0,
237            rtp_timestamp: 0,
238            packet_count: 0,
239            octet_count: 0,
240            blocks: Vec::new(),
241        }
242    }
243
244    /// Decode sender report.
245    pub fn decode(packet: &RtcpPacket) -> Result<Self, InvalidInput> {
246        let header = packet.header();
247
248        let mut data = packet.stripped_payload();
249
250        if data.len() < std::mem::size_of::<RawSenderReportHeader>() {
251            return Err(InvalidInput);
252        }
253
254        let ptr = data.as_ptr() as *const RawSenderReportHeader;
255        let raw = unsafe { &*ptr };
256
257        let mut res = Self {
258            ssrc: u32::from_be(raw.ssrc),
259            ntp_timestamp: u64::from_be(raw.ntp_timestamp),
260            rtp_timestamp: u32::from_be(raw.rtp_timestamp),
261            packet_count: u32::from_be(raw.packet_count),
262            octet_count: u32::from_be(raw.octet_count),
263            blocks: Vec::with_capacity(header.item_count() as usize),
264        };
265
266        data.advance(std::mem::size_of::<RawSenderReportHeader>());
267
268        for _ in 0..header.item_count() {
269            res.blocks.push(ReportBlock::decode(&mut data)?);
270        }
271
272        Ok(res)
273    }
274
275    /// Encode the sender report.
276    pub fn encode(&self) -> RtcpPacket {
277        let mut payload = BytesMut::with_capacity(self.raw_size());
278
279        let raw = RawSenderReportHeader {
280            ssrc: self.ssrc.to_be(),
281            ntp_timestamp: self.ntp_timestamp.to_be(),
282            rtp_timestamp: self.rtp_timestamp.to_be(),
283            packet_count: self.packet_count.to_be(),
284            octet_count: self.octet_count.to_be(),
285        };
286
287        let ptr = &raw as *const _ as *const u8;
288
289        let data = unsafe {
290            std::slice::from_raw_parts(ptr, std::mem::size_of::<RawSenderReportHeader>())
291        };
292
293        payload.extend_from_slice(data);
294
295        for block in &self.blocks {
296            block.encode(&mut payload);
297        }
298
299        RtcpPacket::new(RtcpPacketType::SR)
300            .with_item_count(self.blocks.len() as u8)
301            .with_payload(payload.freeze(), 0)
302    }
303
304    /// Get SSRC identifier of the sender.
305    #[inline]
306    pub fn ssrc(&self) -> u32 {
307        self.ssrc
308    }
309
310    /// Set the SSRC identifier of the sender.
311    #[inline]
312    pub fn with_ssrc(mut self, ssrc: u32) -> Self {
313        self.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.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.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.blocks.len()
398    }
399}
400
401impl Default for SenderReport {
402    #[inline]
403    fn default() -> Self {
404        Self::new()
405    }
406}
407
408/// Receiver report.
409#[derive(Clone)]
410pub struct ReceiverReport {
411    ssrc: u32,
412    blocks: Vec<ReportBlock>,
413}
414
415impl ReceiverReport {
416    /// Create a new receiver report.
417    #[inline]
418    pub const fn new() -> Self {
419        Self {
420            ssrc: 0,
421            blocks: Vec::new(),
422        }
423    }
424
425    /// Decode receiver report.
426    pub fn decode(packet: &RtcpPacket) -> Result<Self, InvalidInput> {
427        let header = packet.header();
428
429        let mut data = packet.stripped_payload();
430
431        if data.len() < 4 {
432            return Err(InvalidInput);
433        }
434
435        let mut res = Self {
436            ssrc: data.get_u32(),
437            blocks: Vec::with_capacity(header.item_count() as usize),
438        };
439
440        for _ in 0..header.item_count() {
441            res.blocks.push(ReportBlock::decode(&mut data)?);
442        }
443
444        Ok(res)
445    }
446
447    /// Encode the sender report.
448    pub fn encode(&self) -> RtcpPacket {
449        let mut payload = BytesMut::with_capacity(self.raw_size());
450
451        payload.put_u32(self.ssrc);
452
453        for block in &self.blocks {
454            block.encode(&mut payload);
455        }
456
457        RtcpPacket::new(RtcpPacketType::RR)
458            .with_item_count(self.blocks.len() as u8)
459            .with_payload(payload.freeze(), 0)
460    }
461
462    /// Get SSRC identifier of the sender.
463    #[inline]
464    pub fn ssrc(&self) -> u32 {
465        self.ssrc
466    }
467
468    /// Set the SSRC identifier of the sender.
469    #[inline]
470    pub fn with_ssrc(mut self, ssrc: u32) -> Self {
471        self.ssrc = ssrc;
472        self
473    }
474
475    /// Get report blocks.
476    #[inline]
477    pub fn report_blocks(&self) -> &[ReportBlock] {
478        &self.blocks
479    }
480
481    /// Set the report blocks.
482    ///
483    /// # Panics
484    /// The method will panic if the number of report blocks is greater than
485    /// 31.
486    #[inline]
487    pub fn with_report_blocks<T>(mut self, blocks: T) -> Self
488    where
489        T: Into<Vec<ReportBlock>>,
490    {
491        let blocks = blocks.into();
492
493        assert!(blocks.len() < 32);
494
495        self.blocks = blocks;
496        self
497    }
498
499    /// Get size of the encoded sender report.
500    #[inline]
501    pub fn raw_size(&self) -> usize {
502        4 + std::mem::size_of::<RawReportBlock>() * self.blocks.len()
503    }
504}
505
506impl Default for ReceiverReport {
507    #[inline]
508    fn default() -> Self {
509        Self::new()
510    }
511}