xref: /webrtc/rtcp/src/extended_report/vm.rs (revision 5d8fe953)
1 use super::*;
2 
3 const 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)]
30 pub struct VoIPMetricsReportBlock {
31     pub ssrc: u32,
32     pub loss_rate: u8,
33     pub discard_rate: u8,
34     pub burst_density: u8,
35     pub gap_density: u8,
36     pub burst_duration: u16,
37     pub gap_duration: u16,
38     pub round_trip_delay: u16,
39     pub end_system_delay: u16,
40     pub signal_level: u8,
41     pub noise_level: u8,
42     pub rerl: u8,
43     pub gmin: u8,
44     pub rfactor: u8,
45     pub ext_rfactor: u8,
46     pub mos_lq: u8,
47     pub mos_cq: u8,
48     pub rx_config: u8,
49     pub reserved: u8,
50     pub jb_nominal: u16,
51     pub jb_maximum: u16,
52     pub jb_abs_max: u16,
53 }
54 
55 impl fmt::Display for VoIPMetricsReportBlock {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result56     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57         write!(f, "{self:?}")
58     }
59 }
60 
61 impl VoIPMetricsReportBlock {
xr_header(&self) -> XRHeader62     pub fn xr_header(&self) -> XRHeader {
63         XRHeader {
64             block_type: BlockType::VoIPMetrics,
65             type_specific: 0,
66             block_length: (self.raw_size() / 4 - 1) as u16,
67         }
68     }
69 }
70 
71 impl Packet for VoIPMetricsReportBlock {
header(&self) -> Header72     fn header(&self) -> Header {
73         Header::default()
74     }
75 
76     /// destination_ssrc returns an array of ssrc values that this report block refers to.
destination_ssrc(&self) -> Vec<u32>77     fn destination_ssrc(&self) -> Vec<u32> {
78         vec![self.ssrc]
79     }
80 
raw_size(&self) -> usize81     fn raw_size(&self) -> usize {
82         XR_HEADER_LENGTH + VM_REPORT_BLOCK_LENGTH as usize
83     }
84 
as_any(&self) -> &(dyn Any + Send + Sync)85     fn as_any(&self) -> &(dyn Any + Send + Sync) {
86         self
87     }
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool88     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
89         other
90             .as_any()
91             .downcast_ref::<VoIPMetricsReportBlock>()
92             .map_or(false, |a| self == a)
93     }
cloned(&self) -> Box<dyn Packet + Send + Sync>94     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
95         Box::new(self.clone())
96     }
97 }
98 
99 impl MarshalSize for VoIPMetricsReportBlock {
marshal_size(&self) -> usize100     fn marshal_size(&self) -> usize {
101         self.raw_size()
102     }
103 }
104 
105 impl Marshal for VoIPMetricsReportBlock {
106     /// marshal_to encodes the VoIPMetricsReportBlock in binary
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>107     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
108         if buf.remaining_mut() < self.marshal_size() {
109             return Err(error::Error::BufferTooShort.into());
110         }
111 
112         let h = self.xr_header();
113         let n = h.marshal_to(buf)?;
114         buf = &mut buf[n..];
115 
116         buf.put_u32(self.ssrc);
117         buf.put_u8(self.loss_rate);
118         buf.put_u8(self.discard_rate);
119         buf.put_u8(self.burst_density);
120         buf.put_u8(self.gap_density);
121         buf.put_u16(self.burst_duration);
122         buf.put_u16(self.gap_duration);
123         buf.put_u16(self.round_trip_delay);
124         buf.put_u16(self.end_system_delay);
125         buf.put_u8(self.signal_level);
126         buf.put_u8(self.noise_level);
127         buf.put_u8(self.rerl);
128         buf.put_u8(self.gmin);
129         buf.put_u8(self.rfactor);
130         buf.put_u8(self.ext_rfactor);
131         buf.put_u8(self.mos_lq);
132         buf.put_u8(self.mos_cq);
133         buf.put_u8(self.rx_config);
134         buf.put_u8(self.reserved);
135         buf.put_u16(self.jb_nominal);
136         buf.put_u16(self.jb_maximum);
137         buf.put_u16(self.jb_abs_max);
138 
139         Ok(self.marshal_size())
140     }
141 }
142 
143 impl Unmarshal for VoIPMetricsReportBlock {
144     /// Unmarshal decodes the VoIPMetricsReportBlock from binary
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,145     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
146     where
147         Self: Sized,
148         B: Buf,
149     {
150         if raw_packet.remaining() < XR_HEADER_LENGTH {
151             return Err(error::Error::PacketTooShort.into());
152         }
153 
154         let xr_header = XRHeader::unmarshal(raw_packet)?;
155         let block_length = xr_header.block_length * 4;
156         if block_length != VM_REPORT_BLOCK_LENGTH || raw_packet.remaining() < block_length as usize
157         {
158             return Err(error::Error::PacketTooShort.into());
159         }
160 
161         let ssrc = raw_packet.get_u32();
162         let loss_rate = raw_packet.get_u8();
163         let discard_rate = raw_packet.get_u8();
164         let burst_density = raw_packet.get_u8();
165         let gap_density = raw_packet.get_u8();
166         let burst_duration = raw_packet.get_u16();
167         let gap_duration = raw_packet.get_u16();
168         let round_trip_delay = raw_packet.get_u16();
169         let end_system_delay = raw_packet.get_u16();
170         let signal_level = raw_packet.get_u8();
171         let noise_level = raw_packet.get_u8();
172         let rerl = raw_packet.get_u8();
173         let gmin = raw_packet.get_u8();
174         let rfactor = raw_packet.get_u8();
175         let ext_rfactor = raw_packet.get_u8();
176         let mos_lq = raw_packet.get_u8();
177         let mos_cq = raw_packet.get_u8();
178         let rx_config = raw_packet.get_u8();
179         let reserved = raw_packet.get_u8();
180         let jb_nominal = raw_packet.get_u16();
181         let jb_maximum = raw_packet.get_u16();
182         let jb_abs_max = raw_packet.get_u16();
183 
184         Ok(VoIPMetricsReportBlock {
185             ssrc,
186             loss_rate,
187             discard_rate,
188             burst_density,
189             gap_density,
190             burst_duration,
191             gap_duration,
192             round_trip_delay,
193             end_system_delay,
194             signal_level,
195             noise_level,
196             rerl,
197             gmin,
198             rfactor,
199             ext_rfactor,
200             mos_lq,
201             mos_cq,
202             rx_config,
203             reserved,
204             jb_nominal,
205             jb_maximum,
206             jb_abs_max,
207         })
208     }
209 }
210