Skip to content
File

Blob: firmware/vendor/str0m/src/packet/g7xx.rs

rust165 lines
1use super::{CodecExtra, Depacketizer, PacketError, Packetizer};
2 
3/// Packetizes G711 RTP packets.
4pub type G711Packetizer = G7xxPacketizer;
5/// Packetizes G722 RTP packets.
6pub type G722Packetizer = G7xxPacketizer;
7 
8/// Generic packetizer for G711 and G722 packets.
9#[derive(Default, Debug, Copy, Clone)]
10pub struct G7xxPacketizer;
11 
12impl Packetizer for G7xxPacketizer {
13 /// Payload fragments an G7xx packet across one or more byte arrays
14 fn packetize(&mut self, mtu: usize, payload: &[u8]) -> Result<Vec<Vec<u8>>, PacketError> {
15 if payload.is_empty() || mtu == 0 {
16 return Ok(vec![]);
17 }
18 
19 let mut payload_data_remaining = payload.len();
20 let mut payload_data_index = 0;
21 let mut payloads = Vec::with_capacity(payload_data_remaining / mtu);
22 while payload_data_remaining > 0 {
23 let current_fragment_size = std::cmp::min(mtu, payload_data_remaining);
24 payloads.push(
25 payload[payload_data_index..payload_data_index + current_fragment_size].to_vec(),
26 );
27 
28 payload_data_remaining -= current_fragment_size;
29 payload_data_index += current_fragment_size;
30 }
31 
32 Ok(payloads)
33 }
34 
35 fn is_marker(&mut self, _data: &[u8], _previous: Option<&[u8]>, _last: bool) -> bool {
36 false
37 }
38}
39 
40/// Depacketizer for G711 packets
41#[derive(PartialEq, Eq, Debug, Default, Clone)]
42pub struct G711Depacketizer;
43 
44impl Depacketizer for G711Depacketizer {
45 fn out_size_hint(&self, packets_size: usize) -> Option<usize> {
46 Some(packets_size)
47 }
48 
49 fn depacketize(
50 &mut self,
51 packet: &[u8],
52 out: &mut Vec<u8>,
53 _: &mut CodecExtra,
54 ) -> Result<(), PacketError> {
55 if !packet.is_empty() {
56 out.extend_from_slice(packet);
57 }
58 
59 Ok(())
60 }
61 
62 fn is_partition_head(&self, _payload: &[u8]) -> bool {
63 true
64 }
65 
66 fn is_partition_tail(&self, _marker: bool, _payload: &[u8]) -> bool {
67 true
68 }
69}
70 
71#[cfg(test)]
72mod test {
73 use super::*;
74 
75 #[test]
76 fn test_g7xx_payload() -> Result<(), PacketError> {
77 let mut pck = G711Packetizer::default();
78 
79 const TEST_LEN: usize = 10000;
80 const TEST_MTU: usize = 1500;
81 
82 //generate random 8-bit g722 samples
83 let samples: Vec<u8> = (0..TEST_LEN).map(|_| fastrand::u8(..)).collect();
84 
85 //make a copy, for packetizer input
86 let mut samples_in = vec![0u8; TEST_LEN];
87 samples_in.clone_from_slice(&samples);
88 let samples_in = samples_in.to_vec();
89 
90 //split our samples into payloads
91 let payloads = pck.packetize(TEST_MTU, &samples_in)?;
92 
93 let outcnt = ((TEST_LEN as f64) / (TEST_MTU as f64)).ceil() as usize;
94 assert_eq!(
95 outcnt,
96 payloads.len(),
97 "Generated {} payloads instead of {}",
98 payloads.len(),
99 outcnt
100 );
101 assert_eq!(&samples, &samples_in, "Modified input samples");
102 
103 let samples_out = payloads.concat();
104 assert_eq!(&samples_out, &samples_in, "Output samples don't match");
105 
106 let empty = &[];
107 let payload = &[0x90, 0x90, 0x90];
108 
109 // Positive MTU, empty payload
110 let result = pck.packetize(1, empty)?;
111 assert!(result.is_empty(), "Generated payload should be empty");
112 
113 // 0 MTU, small payload
114 let result = pck.packetize(0, payload)?;
115 assert_eq!(result.len(), 0, "Generated payload should be empty");
116 
117 // Positive MTU, small payload
118 let result = pck.packetize(10, payload)?;
119 assert_eq!(result.len(), 1, "Generated payload should be the 1");
120 
121 Ok(())
122 }
123 
124 #[test]
125 fn test_g7xx_unmarshal() -> Result<(), PacketError> {
126 let mut pck = G711Depacketizer;
127 let mut extra = CodecExtra::None;
128 
129 // Empty packet
130 let empty_bytes = &[];
131 let mut out = Vec::new();
132 let result = pck.depacketize(empty_bytes, &mut out, &mut extra);
133 assert!(
134 result.is_ok(),
135 "Result should not be err in case of empty packet"
136 );
137 
138 // Normal packet
139 let raw_bytes: &[u8] = &[0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x90];
140 let mut out = Vec::new();
141 pck.depacketize(raw_bytes, &mut out, &mut extra)?;
142 assert_eq!(raw_bytes, &out, "Payload must be same");
143 
144 Ok(())
145 }
146 
147 #[test]
148 fn packetize_respects_mtu() -> Result<(), PacketError> {
149 let payload = vec![0xABu8; 2000];
150 for &mtu in &[100usize, 300, 600, 1200] {
151 let mut pck = G711Packetizer::default();
152 let pkts = pck.packetize(mtu, &payload)?;
153 assert!(!pkts.is_empty(), "G7xx produced no packets at mtu {mtu}");
154 for (i, pkt) in pkts.iter().enumerate() {
155 assert!(
156 pkt.len() <= mtu,
157 "G7xx packet {i} size {} > mtu {mtu}",
158 pkt.len()
159 );
160 }
161 }
162 Ok(())
163 }
164}