1#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct RtpHeader {
6 pub version: u8,
8 pub padding: bool,
10 pub extension: bool,
12 pub csrc_count: u8,
14 pub marker: bool,
16 pub payload_type: u8,
18 pub sequence: u16,
20 pub timestamp: u32,
22 pub ssrc: u32,
24 pub csrc: Vec<u32>,
26 pub extension_data: Option<Vec<u8>>,
28}
29
30impl RtpHeader {
31 pub fn new(payload_type: u8, sequence: u16, timestamp: u32, ssrc: u32) -> Self {
33 Self {
34 version: 2,
35 padding: false,
36 extension: false,
37 csrc_count: 0,
38 marker: false,
39 payload_type,
40 sequence,
41 timestamp,
42 ssrc,
43 csrc: Vec::new(),
44 extension_data: None,
45 }
46 }
47
48 pub fn with_marker(mut self) -> Self {
50 self.marker = true;
51 self
52 }
53
54 pub fn parse(data: &[u8]) -> Option<Self> {
56 if data.len() < 12 {
57 return None;
58 }
59
60 let version = (data[0] >> 6) & 0x03;
61 if version != 2 {
62 return None; }
64
65 let padding = (data[0] & 0x20) != 0;
66 let extension = (data[0] & 0x10) != 0;
67 let csrc_count = data[0] & 0x0F;
68 let marker = (data[1] & 0x80) != 0;
69 let payload_type = data[1] & 0x7F;
70 let sequence = u16::from_be_bytes([data[2], data[3]]);
71 let timestamp = u32::from_be_bytes([data[4], data[5], data[6], data[7]]);
72 let ssrc = u32::from_be_bytes([data[8], data[9], data[10], data[11]]);
73
74 let mut header = Self {
75 version,
76 padding,
77 extension,
78 csrc_count,
79 marker,
80 payload_type,
81 sequence,
82 timestamp,
83 ssrc,
84 csrc: Vec::new(),
85 extension_data: None,
86 };
87
88 let csrc_end = 12 + (csrc_count as usize) * 4;
90 if data.len() < csrc_end {
91 return None;
92 }
93 for i in 0..csrc_count as usize {
94 let offset = 12 + i * 4;
95 let csrc = u32::from_be_bytes([
96 data[offset],
97 data[offset + 1],
98 data[offset + 2],
99 data[offset + 3],
100 ]);
101 header.csrc.push(csrc);
102 }
103
104 if extension {
106 if data.len() < csrc_end + 4 {
107 return None;
108 }
109 let ext_len = u16::from_be_bytes([data[csrc_end + 2], data[csrc_end + 3]]) as usize * 4;
110 let ext_end = csrc_end + 4 + ext_len;
111 if data.len() < ext_end {
112 return None;
113 }
114 header.extension_data = Some(data[csrc_end..ext_end].to_vec());
115 }
116
117 Some(header)
118 }
119
120 pub fn to_bytes(&self) -> Vec<u8> {
122 let mut buf = Vec::with_capacity(12 + self.csrc.len() * 4);
123
124 let byte0 = (self.version << 6)
126 | (if self.padding { 0x20 } else { 0 })
127 | (if self.extension { 0x10 } else { 0 })
128 | (self.csrc.len() as u8 & 0x0F);
129 buf.push(byte0);
130
131 let byte1 = (if self.marker { 0x80 } else { 0 }) | (self.payload_type & 0x7F);
133 buf.push(byte1);
134
135 buf.extend_from_slice(&self.sequence.to_be_bytes());
137
138 buf.extend_from_slice(&self.timestamp.to_be_bytes());
140
141 buf.extend_from_slice(&self.ssrc.to_be_bytes());
143
144 for csrc in &self.csrc {
146 buf.extend_from_slice(&csrc.to_be_bytes());
147 }
148
149 if let Some(ref ext) = self.extension_data {
151 buf.extend_from_slice(ext);
152 }
153
154 buf
155 }
156
157 pub fn header_length(&self) -> usize {
159 let base = 12 + self.csrc.len() * 4;
160 if let Some(ref ext) = self.extension_data {
161 base + ext.len()
162 } else {
163 base
164 }
165 }
166}
167
168impl Default for RtpHeader {
169 fn default() -> Self {
170 Self::new(0, 0, 0, 0)
171 }
172}
173
174#[derive(Debug, Clone)]
176pub struct RtpPacket {
177 pub header: RtpHeader,
179 pub payload: Vec<u8>,
181}
182
183impl RtpPacket {
184 pub fn new(header: RtpHeader, payload: Vec<u8>) -> Self {
186 Self { header, payload }
187 }
188
189 pub fn simple(
191 payload_type: u8,
192 sequence: u16,
193 timestamp: u32,
194 ssrc: u32,
195 payload: Vec<u8>,
196 ) -> Self {
197 Self {
198 header: RtpHeader::new(payload_type, sequence, timestamp, ssrc),
199 payload,
200 }
201 }
202
203 pub fn parse(data: &[u8]) -> Option<Self> {
205 let header = RtpHeader::parse(data)?;
206 let payload_offset = header.header_length();
207 if payload_offset > data.len() {
208 return None;
209 }
210 Some(Self {
211 header,
212 payload: data[payload_offset..].to_vec(),
213 })
214 }
215
216 pub fn to_bytes(&self) -> Vec<u8> {
218 let mut buf = self.header.to_bytes();
219 buf.extend_from_slice(&self.payload);
220 buf
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_header_roundtrip() {
230 let header = RtpHeader::new(8, 1234, 160000, 0xDEADBEEF);
231 let bytes = header.to_bytes();
232 let parsed = RtpHeader::parse(&bytes).unwrap();
233
234 assert_eq!(header.payload_type, parsed.payload_type);
235 assert_eq!(header.sequence, parsed.sequence);
236 assert_eq!(header.timestamp, parsed.timestamp);
237 assert_eq!(header.ssrc, parsed.ssrc);
238 }
239
240 #[test]
241 fn test_header_with_marker() {
242 let header = RtpHeader::new(0, 1, 160, 0x12345678).with_marker();
243 let bytes = header.to_bytes();
244 assert!(bytes[1] & 0x80 != 0);
245 }
246
247 #[test]
248 fn test_packet_roundtrip() {
249 let packet = RtpPacket::simple(0, 100, 16000, 0xABCDEF01, vec![1, 2, 3, 4, 5]);
250 let bytes = packet.to_bytes();
251 let parsed = RtpPacket::parse(&bytes).unwrap();
252
253 assert_eq!(packet.header.sequence, parsed.header.sequence);
254 assert_eq!(packet.payload, parsed.payload);
255 }
256
257 #[test]
258 fn test_header_with_csrc() {
259 let mut header = RtpHeader::new(0, 1, 160, 0x12345678);
260 header.csrc.push(0xAAAAAAAA);
261 header.csrc.push(0xBBBBBBBB);
262
263 let bytes = header.to_bytes();
264 let parsed = RtpHeader::parse(&bytes).unwrap();
265
266 assert_eq!(parsed.csrc.len(), 2);
267 assert_eq!(parsed.csrc[0], 0xAAAAAAAA);
268 assert_eq!(parsed.csrc[1], 0xBBBBBBBB);
269 }
270
271 #[test]
272 fn test_invalid_version() {
273 let data = [
275 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA0, 0x12, 0x34, 0x56, 0x78,
276 ];
277 assert!(RtpHeader::parse(&data).is_none());
278 }
279
280 #[test]
281 fn test_packet_too_short() {
282 assert!(RtpHeader::parse(&[0x80, 0x00, 0x00]).is_none());
284 assert!(RtpHeader::parse(&[]).is_none());
285 }
286
287 #[test]
288 fn test_header_default() {
289 let header = RtpHeader::default();
290 assert_eq!(header.version, 2);
291 assert_eq!(header.payload_type, 0);
292 assert_eq!(header.sequence, 0);
293 assert_eq!(header.timestamp, 0);
294 assert_eq!(header.ssrc, 0);
295 assert!(!header.marker);
296 assert!(!header.padding);
297 assert!(!header.extension);
298 }
299
300 #[test]
301 fn test_all_payload_types() {
302 for pt in 0u8..128 {
304 let header = RtpHeader::new(pt, 1, 160, 0x12345678);
305 let bytes = header.to_bytes();
306 let parsed = RtpHeader::parse(&bytes).unwrap();
307 assert_eq!(parsed.payload_type, pt);
308 }
309 }
310
311 #[test]
312 fn test_sequence_wrap() {
313 let header = RtpHeader::new(0, 65535, 160, 0x12345678);
314 let bytes = header.to_bytes();
315 let parsed = RtpHeader::parse(&bytes).unwrap();
316 assert_eq!(parsed.sequence, 65535);
317
318 let header2 = RtpHeader::new(0, 0, 320, 0x12345678);
319 let bytes2 = header2.to_bytes();
320 let parsed2 = RtpHeader::parse(&bytes2).unwrap();
321 assert_eq!(parsed2.sequence, 0);
322 }
323
324 #[test]
325 fn test_timestamp_max() {
326 let header = RtpHeader::new(0, 1, u32::MAX, 0x12345678);
327 let bytes = header.to_bytes();
328 let parsed = RtpHeader::parse(&bytes).unwrap();
329 assert_eq!(parsed.timestamp, u32::MAX);
330 }
331
332 #[test]
333 fn test_header_length() {
334 let mut header = RtpHeader::new(0, 1, 160, 0x12345678);
335 assert_eq!(header.header_length(), 12);
336
337 header.csrc.push(0xAAAAAAAA);
338 assert_eq!(header.header_length(), 16);
339
340 header.csrc.push(0xBBBBBBBB);
341 assert_eq!(header.header_length(), 20);
342 }
343
344 #[test]
345 fn test_padding_flag() {
346 let mut header = RtpHeader::new(0, 1, 160, 0x12345678);
347 header.padding = true;
348
349 let bytes = header.to_bytes();
350 assert!(bytes[0] & 0x20 != 0);
351
352 let parsed = RtpHeader::parse(&bytes).unwrap();
353 assert!(parsed.padding);
354 }
355
356 #[test]
357 fn test_extension_flag() {
358 let mut header = RtpHeader::new(0, 1, 160, 0x12345678);
359 header.extension = true;
360 header.extension_data = Some(vec![0xBE, 0xDE, 0x00, 0x00]);
362
363 let bytes = header.to_bytes();
364 assert!(bytes[0] & 0x10 != 0);
365
366 let parsed = RtpHeader::parse(&bytes).unwrap();
367 assert!(parsed.extension);
368 assert!(parsed.extension_data.is_some());
369 }
370
371 #[test]
372 fn test_csrc_count_max() {
373 let mut header = RtpHeader::new(0, 1, 160, 0x12345678);
374 for i in 0..15 {
376 header.csrc.push(0x11111111 * (i + 1));
377 }
378
379 let bytes = header.to_bytes();
380 let parsed = RtpHeader::parse(&bytes).unwrap();
381 assert_eq!(parsed.csrc.len(), 15);
382 }
383
384 #[test]
385 fn test_truncated_csrc() {
386 let data = [
388 0x82, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA0, 0x12, 0x34, 0x56, 0x78,
390 0xAA, 0xAA, 0xAA, 0xAA,
392 ];
393 assert!(RtpHeader::parse(&data).is_none());
394 }
395
396 #[test]
397 fn test_packet_with_payload() {
398 let payload = vec![0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE];
399 let packet = RtpPacket::simple(0, 1, 160, 0x12345678, payload.clone());
400
401 let bytes = packet.to_bytes();
402 assert_eq!(bytes.len(), 12 + 8);
403
404 let parsed = RtpPacket::parse(&bytes).unwrap();
405 assert_eq!(parsed.payload, payload);
406 }
407
408 #[test]
409 fn test_packet_empty_payload() {
410 let packet = RtpPacket::simple(0, 1, 160, 0x12345678, vec![]);
411 let bytes = packet.to_bytes();
412 assert_eq!(bytes.len(), 12);
413
414 let parsed = RtpPacket::parse(&bytes).unwrap();
415 assert!(parsed.payload.is_empty());
416 }
417
418 #[test]
419 fn test_rtp_packet_new() {
420 let header = RtpHeader::new(8, 100, 16000, 0xABCDEF01);
421 let packet = RtpPacket::new(header.clone(), vec![1, 2, 3]);
422
423 assert_eq!(packet.header.payload_type, 8);
424 assert_eq!(packet.payload, vec![1, 2, 3]);
425 }
426}