Skip to main content

rtc_rtcp/extended_report/
vm.rs

1use super::*;
2
3const VM_REPORT_BLOCK_LENGTH: u16 = 4 + 4 + 2 * 4 + 10 + 2 * 3;
4
5/// VoIPMetricsReportBlock encodes a VoIP Metrics Report Block as described
6/// in RFC 3611, section 4.7.
7///
8///  0                   1                   2                   3
9///  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
10/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11/// |     BT=7      |   reserved    |       block length = 8        |
12/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13/// |                        ssrc of source                         |
14/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15/// |   loss rate   | discard rate  | burst density |  gap density  |
16/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17/// |       burst duration          |         gap duration          |
18/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19/// |     round trip delay          |       end system delay        |
20/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21/// | signal level  |  noise level  |     RERL      |     Gmin      |
22/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23/// |   R factor    | ext. R factor |    MOS-LQ     |    MOS-CQ     |
24/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25/// |   RX config   |   reserved    |          JB nominal           |
26/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27/// |          JB maximum           |          JB abs max           |
28/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29#[derive(Debug, Default, PartialEq, Eq, Clone)]
30pub struct VoIPMetricsReportBlock {
31    /// The SSRC these metrics describe.
32    pub ssrc: u32,
33    /// Fraction of packets lost, as 256ths.
34    pub loss_rate: u8,
35    /// Fraction of packets discarded by the jitter buffer, as 256ths.
36    pub discard_rate: u8,
37    /// Fraction of packets lost or discarded during bursts, as 256ths.
38    pub burst_density: u8,
39    /// Fraction lost or discarded during gaps between bursts, as 256ths.
40    pub gap_density: u8,
41    /// Mean burst length in milliseconds.
42    pub burst_duration: u16,
43    /// Mean gap length in milliseconds.
44    pub gap_duration: u16,
45    /// Round-trip delay in milliseconds.
46    pub round_trip_delay: u16,
47    /// End-system delay in milliseconds, covering encode, buffer and decode.
48    pub end_system_delay: u16,
49    /// Signal level in dBm0.
50    pub signal_level: u8,
51    /// Noise level in dBm0.
52    pub noise_level: u8,
53    /// Residual echo return loss, in dB.
54    pub rerl: u8,
55    /// The gap threshold: consecutive received packets needed to end a burst.
56    pub gmin: u8,
57    /// The R factor, a 0–100 voice-quality estimate.
58    pub rfactor: u8,
59    /// An external-network R factor, for the segment beyond this one.
60    pub ext_rfactor: u8,
61    /// Listening-quality mean opinion score, in tenths.
62    pub mos_lq: u8,
63    /// Conversational-quality mean opinion score, in tenths.
64    pub mos_cq: u8,
65    /// Receiver configuration: packet-loss concealment and jitter-buffer flags.
66    pub rx_config: u8,
67    /// Reserved; sent as zero.
68    pub reserved: u8,
69    /// Nominal jitter-buffer delay in milliseconds.
70    pub jb_nominal: u16,
71    /// Maximum jitter-buffer delay in milliseconds.
72    pub jb_maximum: u16,
73    /// The absolute maximum the jitter buffer can grow to, in milliseconds.
74    pub jb_abs_max: u16,
75}
76
77impl fmt::Display for VoIPMetricsReportBlock {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        write!(f, "{self:?}")
80    }
81}
82
83impl VoIPMetricsReportBlock {
84    /// The XR block header describing this block's type and length.
85    pub fn xr_header(&self) -> XRHeader {
86        XRHeader {
87            block_type: BlockType::VoIPMetrics,
88            type_specific: 0,
89            block_length: (self.raw_size() / 4 - 1) as u16,
90        }
91    }
92}
93
94impl Packet for VoIPMetricsReportBlock {
95    fn header(&self) -> Header {
96        Header::default()
97    }
98
99    /// destination_ssrc returns an array of ssrc values that this report block refers to.
100    fn destination_ssrc(&self) -> Vec<u32> {
101        vec![self.ssrc]
102    }
103
104    fn raw_size(&self) -> usize {
105        XR_HEADER_LENGTH + VM_REPORT_BLOCK_LENGTH as usize
106    }
107
108    fn as_any(&self) -> &dyn Any {
109        self
110    }
111    fn equal(&self, other: &dyn Packet) -> bool {
112        other.as_any().downcast_ref::<VoIPMetricsReportBlock>() == Some(self)
113    }
114    fn cloned(&self) -> Box<dyn Packet> {
115        Box::new(self.clone())
116    }
117}
118
119impl MarshalSize for VoIPMetricsReportBlock {
120    fn marshal_size(&self) -> usize {
121        self.raw_size()
122    }
123}
124
125impl Marshal for VoIPMetricsReportBlock {
126    /// marshal_to encodes the VoIPMetricsReportBlock in binary
127    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
128        if buf.remaining_mut() < self.marshal_size() {
129            return Err(Error::BufferTooShort);
130        }
131
132        let h = self.xr_header();
133        let n = h.marshal_to(buf)?;
134        buf = &mut buf[n..];
135
136        buf.put_u32(self.ssrc);
137        buf.put_u8(self.loss_rate);
138        buf.put_u8(self.discard_rate);
139        buf.put_u8(self.burst_density);
140        buf.put_u8(self.gap_density);
141        buf.put_u16(self.burst_duration);
142        buf.put_u16(self.gap_duration);
143        buf.put_u16(self.round_trip_delay);
144        buf.put_u16(self.end_system_delay);
145        buf.put_u8(self.signal_level);
146        buf.put_u8(self.noise_level);
147        buf.put_u8(self.rerl);
148        buf.put_u8(self.gmin);
149        buf.put_u8(self.rfactor);
150        buf.put_u8(self.ext_rfactor);
151        buf.put_u8(self.mos_lq);
152        buf.put_u8(self.mos_cq);
153        buf.put_u8(self.rx_config);
154        buf.put_u8(self.reserved);
155        buf.put_u16(self.jb_nominal);
156        buf.put_u16(self.jb_maximum);
157        buf.put_u16(self.jb_abs_max);
158
159        Ok(self.marshal_size())
160    }
161}
162
163impl Unmarshal for VoIPMetricsReportBlock {
164    /// Unmarshal decodes the VoIPMetricsReportBlock from binary
165    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
166    where
167        Self: Sized,
168        B: Buf,
169    {
170        if raw_packet.remaining() < XR_HEADER_LENGTH {
171            return Err(Error::PacketTooShort);
172        }
173
174        let xr_header = XRHeader::unmarshal(raw_packet)?;
175        let block_length = match xr_header.block_length.checked_mul(4) {
176            Some(length) => length,
177            None => return Err(Error::InvalidBlockSize),
178        };
179        if block_length != VM_REPORT_BLOCK_LENGTH || raw_packet.remaining() < block_length as usize
180        {
181            return Err(Error::PacketTooShort);
182        }
183
184        let ssrc = raw_packet.get_u32();
185        let loss_rate = raw_packet.get_u8();
186        let discard_rate = raw_packet.get_u8();
187        let burst_density = raw_packet.get_u8();
188        let gap_density = raw_packet.get_u8();
189        let burst_duration = raw_packet.get_u16();
190        let gap_duration = raw_packet.get_u16();
191        let round_trip_delay = raw_packet.get_u16();
192        let end_system_delay = raw_packet.get_u16();
193        let signal_level = raw_packet.get_u8();
194        let noise_level = raw_packet.get_u8();
195        let rerl = raw_packet.get_u8();
196        let gmin = raw_packet.get_u8();
197        let rfactor = raw_packet.get_u8();
198        let ext_rfactor = raw_packet.get_u8();
199        let mos_lq = raw_packet.get_u8();
200        let mos_cq = raw_packet.get_u8();
201        let rx_config = raw_packet.get_u8();
202        let reserved = raw_packet.get_u8();
203        let jb_nominal = raw_packet.get_u16();
204        let jb_maximum = raw_packet.get_u16();
205        let jb_abs_max = raw_packet.get_u16();
206
207        Ok(VoIPMetricsReportBlock {
208            ssrc,
209            loss_rate,
210            discard_rate,
211            burst_density,
212            gap_density,
213            burst_duration,
214            gap_duration,
215            round_trip_delay,
216            end_system_delay,
217            signal_level,
218            noise_level,
219            rerl,
220            gmin,
221            rfactor,
222            ext_rfactor,
223            mos_lq,
224            mos_cq,
225            rx_config,
226            reserved,
227            jb_nominal,
228            jb_maximum,
229            jb_abs_max,
230        })
231    }
232}