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    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
55impl fmt::Display for VoIPMetricsReportBlock {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        write!(f, "{self:?}")
58    }
59}
60
61impl VoIPMetricsReportBlock {
62    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
71impl Packet for VoIPMetricsReportBlock {
72    fn header(&self) -> Header {
73        Header::default()
74    }
75
76    /// destination_ssrc returns an array of ssrc values that this report block refers to.
77    fn destination_ssrc(&self) -> Vec<u32> {
78        vec![self.ssrc]
79    }
80
81    fn raw_size(&self) -> usize {
82        XR_HEADER_LENGTH + VM_REPORT_BLOCK_LENGTH as usize
83    }
84
85    fn as_any(&self) -> &dyn Any {
86        self
87    }
88    fn equal(&self, other: &dyn Packet) -> bool {
89        other.as_any().downcast_ref::<VoIPMetricsReportBlock>() == Some(self)
90    }
91    fn cloned(&self) -> Box<dyn Packet> {
92        Box::new(self.clone())
93    }
94}
95
96impl MarshalSize for VoIPMetricsReportBlock {
97    fn marshal_size(&self) -> usize {
98        self.raw_size()
99    }
100}
101
102impl Marshal for VoIPMetricsReportBlock {
103    /// marshal_to encodes the VoIPMetricsReportBlock in binary
104    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
105        if buf.remaining_mut() < self.marshal_size() {
106            return Err(Error::BufferTooShort);
107        }
108
109        let h = self.xr_header();
110        let n = h.marshal_to(buf)?;
111        buf = &mut buf[n..];
112
113        buf.put_u32(self.ssrc);
114        buf.put_u8(self.loss_rate);
115        buf.put_u8(self.discard_rate);
116        buf.put_u8(self.burst_density);
117        buf.put_u8(self.gap_density);
118        buf.put_u16(self.burst_duration);
119        buf.put_u16(self.gap_duration);
120        buf.put_u16(self.round_trip_delay);
121        buf.put_u16(self.end_system_delay);
122        buf.put_u8(self.signal_level);
123        buf.put_u8(self.noise_level);
124        buf.put_u8(self.rerl);
125        buf.put_u8(self.gmin);
126        buf.put_u8(self.rfactor);
127        buf.put_u8(self.ext_rfactor);
128        buf.put_u8(self.mos_lq);
129        buf.put_u8(self.mos_cq);
130        buf.put_u8(self.rx_config);
131        buf.put_u8(self.reserved);
132        buf.put_u16(self.jb_nominal);
133        buf.put_u16(self.jb_maximum);
134        buf.put_u16(self.jb_abs_max);
135
136        Ok(self.marshal_size())
137    }
138}
139
140impl Unmarshal for VoIPMetricsReportBlock {
141    /// Unmarshal decodes the VoIPMetricsReportBlock from binary
142    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
143    where
144        Self: Sized,
145        B: Buf,
146    {
147        if raw_packet.remaining() < XR_HEADER_LENGTH {
148            return Err(Error::PacketTooShort);
149        }
150
151        let xr_header = XRHeader::unmarshal(raw_packet)?;
152        let block_length = match xr_header.block_length.checked_mul(4) {
153            Some(length) => length,
154            None => return Err(Error::InvalidBlockSize),
155        };
156        if block_length != VM_REPORT_BLOCK_LENGTH || raw_packet.remaining() < block_length as usize
157        {
158            return Err(Error::PacketTooShort);
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}