rtp_types/
builder.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use std::marker::PhantomData;
4
5use crate::RtpPacket;
6
7/// Errors produced when wrting a packet
8#[derive(Debug, PartialEq, Eq, thiserror::Error)]
9pub enum RtpWriteError {
10    /// Output buffer is not large enough to fit the resulting buffer.  The requested size is
11    /// returned.
12    #[error("Output buffer is not large enough to fit the resulting buffer. Requested size: {}", .0)]
13    OutputTooSmall(usize),
14    /// The payload type provided is not valid.
15    #[error("Invalid payload type {}", .0)]
16    InvalidPayloadType(u8),
17    /// The requested packet is too large.
18    #[error("Packet is too large")]
19    PacketTooLarge,
20    /// Too many Contribution Sources specified.  The number of requested Contribution sources is
21    /// returned.
22    #[error("Too many contribution sources: {}", .0)]
23    TooManyContributionSources(usize),
24    /// The extension data is not padded to a multiple of 4 bytes.
25    #[error("Extension data is not padded to a multiple of 4")]
26    ExtensionDataNotPadded,
27    /// Padding value is invalid.
28    #[error("Value used for padding is invalid")]
29    InvalidPadding,
30}
31
32/// Struct for building a new RTP packet.
33#[derive(Debug)]
34#[must_use = "The builder must be built to be used"]
35pub struct RtpPacketBuilder<P: PayloadLength, E: PayloadLength> {
36    padding: Option<u8>,
37    csrcs: smallvec::SmallVec<[u32; 15]>,
38    marker_bit: bool,
39    payload_type: u8,
40    sequence_number: u16,
41    timestamp: u32,
42    ssrc: u32,
43    extension: Option<(u16, E)>,
44    payloads: smallvec::SmallVec<[P; 16]>,
45}
46
47impl<P: PayloadLength, E: PayloadLength> Default for RtpPacketBuilder<P, E> {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl<P: PayloadLength, E: PayloadLength> RtpPacketBuilder<P, E> {
54    /// Construct a new packet builder.
55    pub fn new() -> RtpPacketBuilder<P, E> {
56        Self {
57            padding: None,
58            csrcs: smallvec::smallvec![],
59            marker_bit: false,
60            // set to an invalid value to force the user to update
61            payload_type: 0xff,
62            sequence_number: 0,
63            timestamp: 0,
64            ssrc: 0,
65            extension: None,
66            payloads: smallvec::SmallVec::new(),
67        }
68    }
69
70    /// Set the number of padding bytes to use for this packet.
71    pub fn padding(mut self, padding: u8) -> Self {
72        self.padding = Some(padding);
73        self
74    }
75
76    /// Set 1. whether padding is used and 2. the number of padding bytes to use for this packet.
77    pub fn maybe_padding(mut self, padding: Option<u8>) -> Self {
78        self.padding = padding;
79        self
80    }
81
82    /// Add a Contribution Source for this packet.
83    pub fn add_csrc(mut self, csrc: u32) -> Self {
84        self.csrcs.push(csrc);
85        self
86    }
87
88    /// Clear any CSRCs configured for this packet.
89    pub fn clear_csrcs(mut self) -> Self {
90        self.csrcs.clear();
91        self
92    }
93
94    /// Set the marker bit for this packet.
95    #[deprecated = "Use `marker_bit()` instead"]
96    pub fn marker(self, marker: bool) -> Self {
97        self.marker_bit(marker)
98    }
99
100    /// Set the marker bit for this packet.
101    pub fn marker_bit(mut self, marker_bit: bool) -> Self {
102        self.marker_bit = marker_bit;
103        self
104    }
105
106    /// Set the payload type for this packet.
107    pub fn payload_type(mut self, pt: u8) -> Self {
108        self.payload_type = pt;
109        self
110    }
111
112    /// Set the sequence number for this packet.
113    pub fn sequence_number(mut self, sequence: u16) -> Self {
114        self.sequence_number = sequence;
115        self
116    }
117
118    /// Set the RTP timestamp for this packet.
119    pub fn timestamp(mut self, timestamp: u32) -> Self {
120        self.timestamp = timestamp;
121        self
122    }
123
124    /// Set the Sequence source for this packet.
125    pub fn ssrc(mut self, ssrc: u32) -> Self {
126        self.ssrc = ssrc;
127        self
128    }
129
130    /// Set the extension header for this packet.
131    pub fn extension(mut self, extension_id: u16, extension_data: E) -> Self {
132        self.extension = Some((extension_id, extension_data));
133        self
134    }
135
136    /// Clear any extension data configured for this packet.
137    pub fn clear_extension(mut self) -> Self {
138        self.extension = None;
139        self
140    }
141
142    /// Add a chunk of payload data for this packet.
143    ///
144    /// Can be called multiple times, in which case the payload data chunks will be
145    /// concatenated when the final packet is created.
146    pub fn payload(mut self, payload: P) -> Self {
147        self.payloads.push(payload);
148        self
149    }
150
151    /// Clear any payloads currently configured.
152    pub fn clear_payloads(mut self) -> Self {
153        self.payloads.clear();
154        self
155    }
156
157    /// Calculate the size required for writing the packet.
158    pub fn calculate_size(&self) -> Result<usize, RtpWriteError> {
159        let payload_len = self.payloads.iter().map(|p| p.len()).sum::<usize>();
160        let extension_len = if let Some((_ext_id, ext_data)) = self.extension.as_ref() {
161            if ext_data.len() > u16::MAX as usize {
162                return Err(RtpWriteError::PacketTooLarge);
163            }
164            if ext_data.len() % 4 != 0 {
165                return Err(RtpWriteError::ExtensionDataNotPadded);
166            }
167            4 + ext_data.len()
168        } else {
169            0
170        };
171        let mut size = RtpPacket::MIN_RTP_PACKET_LEN;
172        size += self.csrcs.len() * 4;
173        size += extension_len;
174        size += payload_len;
175        if let Some(padding) = self.padding {
176            size += padding as usize;
177        }
178        Ok(size)
179    }
180
181    fn write_header_into(&self, buf: &mut [u8]) -> usize {
182        let mut byte = 0x80; // rtp version 2
183        if self.padding.is_some() {
184            byte |= 0x20;
185        }
186        if self.extension.is_some() {
187            byte |= 0x10;
188        }
189        byte |= (self.csrcs.len() as u8) & 0x0f;
190        buf[0] = byte;
191
192        let mut byte = self.payload_type & 0x7f;
193        if self.marker_bit {
194            byte |= 0x80;
195        }
196        buf[1] = byte;
197
198        buf[2] = (self.sequence_number >> 8) as u8;
199        buf[3] = (self.sequence_number & 0xff) as u8;
200
201        buf[4] = (self.timestamp >> 24) as u8;
202        buf[5] = ((self.timestamp >> 16) & 0xff) as u8;
203        buf[6] = ((self.timestamp >> 8) & 0xff) as u8;
204        buf[7] = (self.timestamp & 0xff) as u8;
205
206        buf[8] = (self.ssrc >> 24) as u8;
207        buf[9] = ((self.ssrc >> 16) & 0xff) as u8;
208        buf[10] = ((self.ssrc >> 8) & 0xff) as u8;
209        buf[11] = (self.ssrc & 0xff) as u8;
210
211        RtpPacket::MIN_RTP_PACKET_LEN
212    }
213
214    fn write_preconditions(&self) -> Result<usize, RtpWriteError> {
215        if self.payload_type > 0x7f {
216            return Err(RtpWriteError::InvalidPayloadType(self.payload_type));
217        }
218        if self.csrcs.len() > RtpPacket::MAX_N_CSRCS {
219            return Err(RtpWriteError::TooManyContributionSources(self.csrcs.len()));
220        }
221
222        if let Some(padding) = self.padding {
223            if padding == 0 {
224                return Err(RtpWriteError::InvalidPadding);
225            }
226        }
227
228        self.calculate_size()
229    }
230
231    /// Write this packet using writer without any validity checks.
232    pub fn write_unchecked<O>(
233        &self,
234        writer: &mut impl RtpPacketWriter<Payload = P, Extension = E, Output = O>,
235    ) -> O {
236        let mut hdr = [0; RtpPacket::MIN_RTP_PACKET_LEN];
237        self.write_header_into(&mut hdr);
238        writer.push(hdr.as_ref());
239
240        for csrc in self.csrcs.iter() {
241            writer.push(csrc.to_be_bytes().as_ref());
242        }
243
244        if let Some((ext_id, ext_data)) = self.extension.as_ref() {
245            writer.push(ext_id.to_be_bytes().as_ref());
246            writer.push(((ext_data.len() / 4) as u16).to_be_bytes().as_ref());
247            writer.push_extension(ext_data);
248        }
249
250        for payload in self.payloads.iter() {
251            writer.push_payload(payload);
252        }
253
254        if let Some(padding) = self.padding {
255            writer.padding(padding);
256        }
257
258        writer.finish()
259    }
260
261    /// Write the packet using writer.
262    pub fn write<O>(
263        &self,
264        writer: &mut impl RtpPacketWriter<Payload = P, Extension = E, Output = O>,
265    ) -> Result<O, RtpWriteError> {
266        let len = self.write_preconditions()?;
267        if let Some(max_size) = writer.max_size() {
268            if max_size < len {
269                return Err(RtpWriteError::OutputTooSmall(len));
270            }
271        }
272
273        writer.reserve(len);
274        Ok(self.write_unchecked(writer))
275    }
276}
277
278impl<'a, 'b> RtpPacketBuilder<&'a [u8], &'b [u8]> {
279    /// Write this packet into `buf` without any validity checks.  Returns the number of bytes
280    /// written.
281    pub fn write_into_unchecked(&self, buf: &mut [u8]) -> usize {
282        let mut writer = RtpPacketWriterMutSlice::new(buf);
283        self.write_unchecked(&mut writer)
284    }
285
286    /// Write this packet into `buf`.  On success returns the number of bytes written or an
287    /// `RtpWriteError` on failure.
288    pub fn write_into(&self, buf: &mut [u8]) -> Result<usize, RtpWriteError> {
289        let mut writer = RtpPacketWriterMutSlice::new(buf);
290        self.write(&mut writer)
291    }
292
293    /// Write this packet into `buf` without any validity checks.  The data will be appended to the
294    /// end of the provide Vec.
295    pub fn write_into_vec_unchecked(&self, buf: &mut Vec<u8>) {
296        let mut writer = RtpPacketWriterMutVec::new(buf);
297        self.write_unchecked(&mut writer)
298    }
299
300    /// Write this packet into `buf`.  The data will be appended to the end of the provide Vec.
301    pub fn write_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), RtpWriteError> {
302        let mut writer = RtpPacketWriterMutVec::new(buf);
303        self.write(&mut writer)
304    }
305
306    /// Write this packet into a newly generated `Vec<u8>` without any validity checks.
307    pub fn write_vec_unchecked(&self) -> Vec<u8> {
308        let mut writer = RtpPacketWriterVec::default();
309        self.write_unchecked(&mut writer)
310    }
311
312    /// Write this packet into a newly generated `Vec<u8>`.
313    pub fn write_vec(&self) -> Result<Vec<u8>, RtpWriteError> {
314        let mut writer = RtpPacketWriterVec::default();
315        self.write(&mut writer)
316    }
317}
318
319/// Trait to provide the length of a piece of data in bytes.
320pub trait PayloadLength {
321    /// The length of the data in bytes.
322    fn len(&self) -> usize;
323    /// Whether the data contains any bytes.
324    fn is_empty(&self) -> bool {
325        self.len() != 0
326    }
327}
328
329/// Trait to write an RTP packet into and/or from custom data types.
330pub trait RtpPacketWriter {
331    /// The type of the output.
332    type Output;
333    /// The type of the RTP payload to be stored in the output packet.
334    type Payload: PayloadLength;
335    /// The type of the RTP extension data to be stored in the output packet:was.
336    type Extension: PayloadLength;
337
338    /// Reserve a number of bytes in the output.  Multiple calls are possible and provide the
339    /// entire size to reserve.
340    fn reserve(&mut self, _size: usize) {}
341
342    /// Return the maximum size of the output.  If the output data is not bound to a fixed size,
343    /// `None` should be returned.
344    fn max_size(&self) -> Option<usize> {
345        None
346    }
347
348    /// Provides data to append to the output.  May be called multiple times per packet.
349    fn push(&mut self, data: &[u8]);
350
351    /// Provides the extension data to add to the output.  The extension should be written as-is
352    /// without any transformations.
353    fn push_extension(&mut self, extension_data: &Self::Extension);
354
355    /// Provides the payload data to add to the output.  The payload should be written as-is
356    /// without any transformations.
357    fn push_payload(&mut self, payload: &Self::Payload);
358
359    /// Provides any padding value the builder was constructed with.  The padding value specifies
360    /// the number of bytes of zeroes of padding at the end to write.  The last byte of padding
361    /// must be set to the padding count.  e.g.
362    ///
363    /// `[..., 0, 0, 0, 4]`
364    fn padding(&mut self, size: u8);
365
366    /// Finishes and returns the built RTP packet.  The implementation should reset internal state
367    /// so that a new packet can be created after `finish` is called.
368    fn finish(&mut self) -> Self::Output;
369}
370
371impl<T> PayloadLength for &[T] {
372    fn len(&self) -> usize {
373        (self as &[T]).len()
374    }
375}
376
377impl<T> PayloadLength for Vec<T> {
378    fn len(&self) -> usize {
379        (self as &Vec<T>).len()
380    }
381}
382
383impl<T, const N: usize> PayloadLength for [T; N] {
384    fn len(&self) -> usize {
385        self.as_slice().len()
386    }
387}
388
389impl<T, const N: usize> PayloadLength for &[T; N] {
390    fn len(&self) -> usize {
391        self.as_slice().len()
392    }
393}
394
395/// An implementation of a [`RtpPacketWriter`] that appends to a `Vec<u8>`.
396#[derive(Default, Debug)]
397pub struct RtpPacketWriterVec<'a, 'b> {
398    output: Vec<u8>,
399    padding: Option<u8>,
400    phantom: PhantomData<(&'a [u8], &'b [u8])>,
401}
402
403impl<'a, 'b> RtpPacketWriter for RtpPacketWriterVec<'a, 'b> {
404    type Output = Vec<u8>;
405    type Payload = &'a [u8];
406    type Extension = &'b [u8];
407
408    fn reserve(&mut self, size: usize) {
409        if self.output.len() < size {
410            self.output.reserve(size - self.output.len());
411        }
412    }
413
414    fn push(&mut self, data: &[u8]) {
415        self.output.extend_from_slice(data)
416    }
417
418    fn push_extension(&mut self, extension_data: &Self::Extension) {
419        self.push(extension_data)
420    }
421
422    fn push_payload(&mut self, data: &Self::Payload) {
423        self.push(data)
424    }
425
426    fn padding(&mut self, size: u8) {
427        self.padding = Some(size);
428    }
429
430    fn finish(&mut self) -> Self::Output {
431        let mut ret = vec![];
432        if let Some(padding) = self.padding.take() {
433            self.output
434                .resize(self.output.len() + padding as usize - 1, 0);
435            self.output.push(padding);
436        }
437        std::mem::swap(&mut ret, &mut self.output);
438        ret
439    }
440}
441
442/// An implementation of a [`RtpPacketWriter`] that writes to a `&mut [u8]`.  Each packet will be
443/// written starting at the beginning of the provided slice.
444#[derive(Default, Debug)]
445pub struct RtpPacketWriterMutSlice<'a, 'b, 'c> {
446    output: &'a mut [u8],
447    padding: Option<u8>,
448    write_i: usize,
449    phantom: PhantomData<(&'b [u8], &'c [u8])>,
450}
451
452impl<'a, 'b, 'c> RtpPacketWriterMutSlice<'a, 'b, 'c> {
453    /// Construct a new [`RtpPacketWriterMutSlice`] from the provided slice.
454    pub fn new(buf: &'a mut [u8]) -> Self {
455        Self {
456            output: buf,
457            padding: None,
458            write_i: 0,
459            phantom: PhantomData,
460        }
461    }
462}
463
464impl<'a, 'b, 'c> std::ops::Deref for RtpPacketWriterMutSlice<'a, 'b, 'c> {
465    type Target = [u8];
466
467    fn deref(&self) -> &Self::Target {
468        self.output
469    }
470}
471
472impl<'a, 'b, 'c> std::ops::DerefMut for RtpPacketWriterMutSlice<'a, 'b, 'c> {
473    fn deref_mut(&mut self) -> &mut Self::Target {
474        self.output
475    }
476}
477
478impl<'a, 'b, 'c> RtpPacketWriter for RtpPacketWriterMutSlice<'a, 'b, 'c> {
479    type Output = usize;
480    type Payload = &'b [u8];
481    type Extension = &'c [u8];
482
483    fn max_size(&self) -> Option<usize> {
484        Some(self.output.len())
485    }
486
487    fn push(&mut self, data: &[u8]) {
488        self.output[self.write_i..self.write_i + data.len()].copy_from_slice(data);
489        self.write_i += data.len();
490    }
491
492    fn push_extension(&mut self, extension_data: &Self::Extension) {
493        self.push(extension_data)
494    }
495
496    fn push_payload(&mut self, data: &Self::Payload) {
497        self.push(data)
498    }
499
500    fn padding(&mut self, size: u8) {
501        self.padding = Some(size);
502    }
503
504    fn finish(&mut self) -> Self::Output {
505        if let Some(padding) = self.padding.take() {
506            if padding > 1 {
507                self.output[self.write_i..self.write_i + padding as usize - 1].fill(0);
508            }
509            self.write_i += padding as usize;
510            self.output[self.write_i - 1] = padding;
511        }
512        let ret = self.write_i;
513        self.write_i = 0;
514        ret
515    }
516}
517
518/// An implementation of a [`RtpPacketWriter`] that writes to a `&mut Vec<u8>`.  Each packet
519/// written will be appended to the provide `Vec<u8>`.  You can `clear()` the vec in between packets
520/// to have each packet written from the beginning of the vec.
521#[derive(Debug)]
522pub struct RtpPacketWriterMutVec<'a, 'b, 'c> {
523    output: &'a mut Vec<u8>,
524    padding: Option<u8>,
525    phantom: PhantomData<(&'b [u8], &'c [u8])>,
526}
527
528impl<'a, 'b, 'c> RtpPacketWriterMutVec<'a, 'b, 'c> {
529    /// Construct a new [`RtpPacketWriterMutVec`] from a provided mutable `Vec<u8>`.
530    pub fn new(buf: &'a mut Vec<u8>) -> Self {
531        Self {
532            output: buf,
533            padding: None,
534            phantom: PhantomData,
535        }
536    }
537}
538
539impl<'a, 'b, 'c> std::ops::Deref for RtpPacketWriterMutVec<'a, 'b, 'c> {
540    type Target = Vec<u8>;
541
542    fn deref(&self) -> &Self::Target {
543        self.output
544    }
545}
546
547impl<'a, 'b, 'c> std::ops::DerefMut for RtpPacketWriterMutVec<'a, 'b, 'c> {
548    fn deref_mut(&mut self) -> &mut Self::Target {
549        self.output
550    }
551}
552
553impl<'a, 'b, 'c> RtpPacketWriter for RtpPacketWriterMutVec<'a, 'b, 'c> {
554    type Output = ();
555    type Payload = &'b [u8];
556    type Extension = &'c [u8];
557
558    fn push(&mut self, data: &[u8]) {
559        self.output.extend(data);
560    }
561
562    fn push_extension(&mut self, extension_data: &Self::Extension) {
563        self.push(extension_data)
564    }
565
566    fn push_payload(&mut self, data: &Self::Payload) {
567        self.push(data)
568    }
569
570    fn padding(&mut self, size: u8) {
571        self.padding = Some(size);
572    }
573
574    fn finish(&mut self) -> Self::Output {
575        if let Some(padding) = self.padding.take() {
576            self.output
577                .extend(std::iter::repeat(0).take(padding as usize - 1));
578            self.output.push(padding);
579        }
580    }
581}
582
583#[cfg(test)]
584mod tests {
585    use super::*;
586
587    #[test]
588    fn write_rtp_default() {
589        let mut data = [0; 128];
590        let mut vec = vec![];
591        let builder = RtpPacketBuilder::new().payload_type(96);
592        let size = builder.write_into(&mut data).unwrap();
593        let buf = builder.write_vec().unwrap();
594        builder.write_into_vec(&mut vec).unwrap();
595        drop(builder);
596        let data = &data[..size];
597        assert_eq!(size, buf.len());
598        assert_eq!(size, vec.len());
599        for data in [data, buf.as_ref(), vec.as_ref()] {
600            println!("{data:?}");
601            let rtp = RtpPacket::parse(data).unwrap();
602            assert_eq!(rtp.version(), 2);
603            assert_eq!(rtp.padding(), None);
604            assert_eq!(rtp.n_csrcs(), 0);
605            assert!(!rtp.marker_bit());
606            assert_eq!(rtp.payload_type(), 96);
607            assert_eq!(rtp.sequence_number(), 0x0);
608            assert_eq!(rtp.timestamp(), 0x0);
609            assert_eq!(rtp.ssrc(), 0x0);
610            assert_eq!(rtp.csrc().count(), 0);
611            assert_eq!(rtp.extension(), None);
612            assert_eq!(rtp.payload(), &[]);
613        }
614    }
615
616    #[test]
617    fn write_rtp_header() {
618        let mut data = [0; 128];
619        let mut vec = vec![];
620        let builder = RtpPacketBuilder::new()
621            .payload_type(96)
622            .marker_bit(true)
623            .sequence_number(0x0102)
624            .timestamp(0x03040506)
625            .ssrc(0x0708090a)
626            .add_csrc(0x0b0c0d0e);
627        let size = builder.write_into(&mut data).unwrap();
628        let buf = builder.write_vec().unwrap();
629        builder.write_into_vec(&mut vec).unwrap();
630        drop(builder);
631        let data = &data[..size];
632        assert_eq!(size, buf.len());
633        assert_eq!(size, vec.len());
634        for data in [data, buf.as_ref(), vec.as_ref()] {
635            println!("{data:?}");
636            let rtp = RtpPacket::parse(data).unwrap();
637            assert_eq!(rtp.version(), 2);
638            assert_eq!(rtp.padding(), None);
639            assert_eq!(rtp.n_csrcs(), 1);
640            assert!(rtp.marker_bit());
641            assert_eq!(rtp.payload_type(), 96);
642            assert_eq!(rtp.sequence_number(), 0x0102);
643            assert_eq!(rtp.timestamp(), 0x03040506);
644            assert_eq!(rtp.ssrc(), 0x0708090a);
645            let mut csrc = rtp.csrc();
646            assert_eq!(csrc.next(), Some(0x0b0c0d0e));
647            assert_eq!(csrc.next(), None);
648            assert_eq!(rtp.extension(), None);
649            assert_eq!(rtp.payload(), &[]);
650        }
651    }
652
653    #[test]
654    fn write_rtp_header_multiple_csrcs() {
655        let mut data = [0; 128];
656        let mut vec = vec![];
657        let builder = RtpPacketBuilder::new()
658            .payload_type(96)
659            .add_csrc(0x01020304)
660            .add_csrc(0x05060708);
661        let size = builder.write_into(&mut data).unwrap();
662        let buf = builder.write_vec().unwrap();
663        builder.write_into_vec(&mut vec).unwrap();
664        drop(builder);
665        let data = &data[..size];
666        assert_eq!(size, buf.len());
667        assert_eq!(size, vec.len());
668        for data in [data, buf.as_ref(), vec.as_ref()] {
669            println!("{data:?}");
670            let rtp = RtpPacket::parse(data).unwrap();
671            assert_eq!(rtp.n_csrcs(), 2);
672            let mut csrc = rtp.csrc();
673            assert_eq!(csrc.next(), Some(0x01020304));
674            assert_eq!(csrc.next(), Some(0x05060708));
675            assert_eq!(csrc.next(), None);
676        }
677    }
678
679    #[test]
680    fn write_rtp_multiple_payloads() {
681        let mut data = [0; 128];
682        let mut vec = vec![];
683        let payload_data = [1, 2, 3, 4, 5, 6, 7, 8];
684        let more_payload_data = [9, 10, 11];
685        let builder = RtpPacketBuilder::new()
686            .payload_type(96)
687            .payload(payload_data.as_ref())
688            .payload(more_payload_data.as_ref())
689            .payload(more_payload_data[0..1].as_ref());
690        let size = builder.write_into(&mut data).unwrap();
691        assert_eq!(size, 24);
692        let buf = builder.write_vec().unwrap();
693        builder.write_into_vec(&mut vec).unwrap();
694        drop(builder);
695        let data = &data[..size];
696        assert_eq!(size, buf.len());
697        assert_eq!(size, vec.len());
698        for data in [data, buf.as_ref(), vec.as_ref()] {
699            println!("{data:?}");
700            let rtp = RtpPacket::parse(data).unwrap();
701            assert_eq!(rtp.version(), 2);
702            assert_eq!(rtp.payload_type(), 96);
703            assert_eq!(rtp.payload(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 9]);
704        }
705    }
706
707    #[test]
708    fn write_rtp_extension() {
709        let mut data = [0; 128];
710        let mut vec = vec![];
711        let extension_data = [1, 2, 3, 4, 5, 6, 7, 8];
712        let builder = RtpPacketBuilder::new()
713            .payload_type(96)
714            .marker_bit(true)
715            .sequence_number(0x0102)
716            .timestamp(0x03040506)
717            .ssrc(0x0708090a)
718            .add_csrc(0x0b0c0d0e)
719            .extension(0x9876, extension_data.as_ref());
720        let size = builder.write_into(&mut data).unwrap();
721        let buf = builder.write_vec().unwrap();
722        builder.write_into_vec(&mut vec).unwrap();
723        drop(builder);
724        let data = &data[..size];
725        assert_eq!(size, buf.len());
726        assert_eq!(size, vec.len());
727        for data in [data, buf.as_ref(), vec.as_ref()] {
728            println!("{data:?}");
729            let rtp = RtpPacket::parse(data).unwrap();
730            assert_eq!(rtp.version(), 2);
731            assert_eq!(rtp.padding(), None);
732            assert_eq!(rtp.n_csrcs(), 1);
733            assert!(rtp.marker_bit());
734            assert_eq!(rtp.payload_type(), 96);
735            assert_eq!(rtp.sequence_number(), 0x0102);
736            assert_eq!(rtp.timestamp(), 0x03040506);
737            assert_eq!(rtp.ssrc(), 0x0708090a);
738            let mut csrc = rtp.csrc();
739            assert_eq!(csrc.next(), Some(0x0b0c0d0e));
740            assert_eq!(csrc.next(), None);
741            assert_eq!(rtp.extension(), Some((0x9876, extension_data.as_ref())));
742            assert_eq!(rtp.payload(), &[]);
743        }
744    }
745
746    #[test]
747    fn write_rtp_extension_payload_padding() {
748        let mut data = [0; 128];
749        let mut vec = vec![];
750        let extension_data = [1, 2, 3, 4, 5, 6, 7, 8];
751        let payload_data = [1, 2, 3, 4, 5, 6, 7, 8];
752        let builder = RtpPacketBuilder::new()
753            .payload_type(96)
754            .marker_bit(true)
755            .sequence_number(0x0102)
756            .timestamp(0x03040506)
757            .ssrc(0x0708090a)
758            .add_csrc(0x0b0c0d0e)
759            .extension(0x9876, extension_data.as_ref())
760            .payload(payload_data.as_ref())
761            .padding(7);
762        let size = builder.write_into(&mut data).unwrap();
763        let buf = builder.write_vec().unwrap();
764        builder.write_into_vec(&mut vec).unwrap();
765        drop(builder);
766        let data = &data[..size];
767        assert_eq!(size, buf.len());
768        assert_eq!(size, vec.len());
769        for data in [data, buf.as_ref(), vec.as_ref()] {
770            println!("{data:?}");
771            let rtp = RtpPacket::parse(data).unwrap();
772            assert_eq!(rtp.version(), 2);
773            assert_eq!(rtp.padding(), Some(7));
774            assert_eq!(rtp.n_csrcs(), 1);
775            assert!(rtp.marker_bit());
776            assert_eq!(rtp.payload_type(), 96);
777            assert_eq!(rtp.sequence_number(), 0x0102);
778            assert_eq!(rtp.timestamp(), 0x03040506);
779            assert_eq!(rtp.ssrc(), 0x0708090a);
780            let mut csrc = rtp.csrc();
781            assert_eq!(csrc.next(), Some(0x0b0c0d0e));
782            assert_eq!(csrc.next(), None);
783            assert_eq!(rtp.extension(), Some((0x9876, extension_data.as_ref())));
784            assert_eq!(rtp.payload(), payload_data.as_ref());
785        }
786    }
787
788    #[test]
789    fn write_rtp_invalid_padding() {
790        let mut data = [0; 128];
791        let mut vec = vec![];
792        let builder = RtpPacketBuilder::new().payload_type(96).padding(0);
793        assert_eq!(
794            builder.write_into(&mut data),
795            Err(RtpWriteError::InvalidPadding)
796        );
797        assert_eq!(builder.write_vec(), Err(RtpWriteError::InvalidPadding));
798        assert_eq!(
799            builder.write_into_vec(&mut vec),
800            Err(RtpWriteError::InvalidPadding)
801        );
802    }
803
804    #[test]
805    fn write_rtp_unpadded_extension() {
806        let mut data = [0; 128];
807        let mut vec = vec![];
808        let builder = RtpPacketBuilder::new()
809            .payload_type(96)
810            .extension(0x9876, [1].as_ref());
811        assert_eq!(
812            builder.write_into(&mut data),
813            Err(RtpWriteError::ExtensionDataNotPadded)
814        );
815        assert_eq!(
816            builder.write_vec(),
817            Err(RtpWriteError::ExtensionDataNotPadded)
818        );
819        assert_eq!(
820            builder.write_into_vec(&mut vec),
821            Err(RtpWriteError::ExtensionDataNotPadded)
822        );
823    }
824
825    #[test]
826    fn write_rtp_invalid_payload_type() {
827        let mut data = [0; 128];
828        let mut vec = vec![];
829        let builder = RtpPacketBuilder::new().payload_type(0xFF);
830        assert_eq!(
831            builder.write_into(&mut data),
832            Err(RtpWriteError::InvalidPayloadType(0xFF))
833        );
834        assert_eq!(
835            builder.write_vec(),
836            Err(RtpWriteError::InvalidPayloadType(0xFF))
837        );
838        assert_eq!(
839            builder.write_into_vec(&mut vec),
840            Err(RtpWriteError::InvalidPayloadType(0xFF))
841        );
842    }
843
844    #[test]
845    fn write_rtp_too_many_contributions() {
846        let mut data = [0; 128];
847        let mut vec = vec![];
848        let builder = RtpPacketBuilder::new()
849            .payload_type(96)
850            .add_csrc(1)
851            .add_csrc(2)
852            .add_csrc(3)
853            .add_csrc(4)
854            .add_csrc(5)
855            .add_csrc(6)
856            .add_csrc(7)
857            .add_csrc(8)
858            .add_csrc(9)
859            .add_csrc(10)
860            .add_csrc(11)
861            .add_csrc(12)
862            .add_csrc(13)
863            .add_csrc(14)
864            .add_csrc(15)
865            .add_csrc(16);
866        assert_eq!(
867            builder.write_into(&mut data),
868            Err(RtpWriteError::TooManyContributionSources(16))
869        );
870        assert_eq!(
871            builder.write_vec(),
872            Err(RtpWriteError::TooManyContributionSources(16))
873        );
874        assert_eq!(
875            builder.write_into_vec(&mut vec),
876            Err(RtpWriteError::TooManyContributionSources(16))
877        );
878    }
879
880    #[test]
881    fn write_rtp_extension_too_large() {
882        let mut data = [0; u16::MAX as usize + 128];
883        let mut vec = vec![];
884        let extension_data = [0; u16::MAX as usize + 1];
885        let builder = RtpPacketBuilder::new()
886            .payload_type(96)
887            .extension(0x9876, extension_data.as_ref());
888        assert_eq!(
889            builder.write_into(&mut data),
890            Err(RtpWriteError::PacketTooLarge)
891        );
892        assert_eq!(builder.write_vec(), Err(RtpWriteError::PacketTooLarge));
893        assert_eq!(
894            builder.write_into_vec(&mut vec),
895            Err(RtpWriteError::PacketTooLarge)
896        );
897    }
898
899    #[test]
900    fn write_rtp_output_too_short() {
901        let mut data = [0; 11];
902        assert_eq!(
903            RtpPacketBuilder::new()
904                .payload_type(96)
905                .write_into(&mut data),
906            Err(RtpWriteError::OutputTooSmall(12))
907        );
908    }
909
910    #[test]
911    fn write_rtp_output_too_short_with_csrc() {
912        let mut data = [0; 15];
913        assert_eq!(
914            RtpPacketBuilder::new()
915                .payload_type(96)
916                .add_csrc(1)
917                .write_into(&mut data),
918            Err(RtpWriteError::OutputTooSmall(16))
919        );
920    }
921
922    #[test]
923    fn write_rtp_output_too_short_extension() {
924        let mut data = [0; 15];
925        assert_eq!(
926            RtpPacketBuilder::new()
927                .payload_type(96)
928                .extension(0x9876, [].as_ref())
929                .write_into(&mut data),
930            Err(RtpWriteError::OutputTooSmall(16))
931        );
932    }
933
934    #[test]
935    fn write_rtp_output_too_short_padding() {
936        let mut data = [0; 12];
937        assert_eq!(
938            RtpPacketBuilder::new()
939                .payload_type(96)
940                .padding(1)
941                .write_into(&mut data),
942            Err(RtpWriteError::OutputTooSmall(13))
943        );
944    }
945
946    #[test]
947    fn write_rtp_output_too_short_payload() {
948        let mut data = [0; 12];
949        assert_eq!(
950            RtpPacketBuilder::new()
951                .payload_type(96)
952                .payload([1].as_ref())
953                .write_into(&mut data),
954            Err(RtpWriteError::OutputTooSmall(13))
955        );
956    }
957
958    #[derive(Debug)]
959    struct TestPayload(Vec<u8>);
960
961    impl PayloadLength for TestPayload {
962        fn len(&self) -> usize {
963            self.0.len()
964        }
965    }
966
967    #[derive(Default, Debug)]
968    struct TestRtpWriterCustomPayload {
969        output: Option<Vec<u8>>,
970        padding: Option<u8>,
971        max_size: usize,
972    }
973
974    impl RtpPacketWriter for TestRtpWriterCustomPayload {
975        type Output = Vec<u8>;
976        type Payload = TestPayload;
977        type Extension = TestPayload;
978
979        fn reserve(&mut self, size: usize) {
980            if let Some(output) = self.output.as_mut() {
981                if output.len() < size {
982                    output.reserve(size - output.len());
983                }
984            } else {
985                self.output = Some(Vec::with_capacity(size));
986            }
987        }
988
989        fn push(&mut self, data: &[u8]) {
990            let p = self
991                .output
992                .get_or_insert_with(|| Vec::with_capacity(data.len()));
993            println!(
994                "push {} bytes at offset {}, max_size {}",
995                data.len(),
996                p.len(),
997                self.max_size
998            );
999            assert!(p.len() + data.len() <= self.max_size);
1000            p.extend_from_slice(data)
1001        }
1002
1003        fn push_payload(&mut self, payload: &Self::Payload) {
1004            self.push(&payload.0)
1005        }
1006
1007        fn push_extension(&mut self, extension_data: &Self::Extension) {
1008            self.push(&extension_data.0)
1009        }
1010
1011        fn padding(&mut self, size: u8) {
1012            self.padding = Some(size);
1013        }
1014
1015        fn finish(&mut self) -> Self::Output {
1016            self.output
1017                .take()
1018                .map(|mut output| {
1019                    if let Some(padding) = self.padding.take() {
1020                        output.extend(std::iter::repeat(0).take(padding as usize - 1));
1021                        output.push(padding);
1022                    }
1023                    output
1024                })
1025                .unwrap_or_default()
1026        }
1027    }
1028
1029    #[test]
1030    fn write_rtp_custom_payload() {
1031        let extension_data = TestPayload(vec![1, 2, 3, 4, 5, 6, 7, 8]);
1032        let payload_data = TestPayload(vec![11, 12, 13, 14, 15, 16, 17, 18]);
1033        let builder = RtpPacketBuilder::new()
1034            .payload_type(96)
1035            .marker_bit(true)
1036            .sequence_number(0x0102)
1037            .timestamp(0x03040506)
1038            .ssrc(0x0708090a)
1039            .add_csrc(0x0b0c0d0e)
1040            .extension(0x9876, TestPayload(extension_data.0.clone()))
1041            .payload(TestPayload(payload_data.0.clone()))
1042            .padding(1);
1043        let max_size = builder.calculate_size().unwrap();
1044        let mut writer = TestRtpWriterCustomPayload {
1045            max_size,
1046            ..Default::default()
1047        };
1048        let buf = builder.write(&mut writer).unwrap();
1049        drop(builder);
1050        let data = buf.as_ref();
1051        println!("{data:?}");
1052        let rtp = RtpPacket::parse(data).unwrap();
1053        assert_eq!(rtp.version(), 2);
1054        assert_eq!(rtp.padding(), Some(1));
1055        assert_eq!(rtp.n_csrcs(), 1);
1056        assert!(rtp.marker_bit());
1057        assert_eq!(rtp.payload_type(), 96);
1058        assert_eq!(rtp.sequence_number(), 0x0102);
1059        assert_eq!(rtp.timestamp(), 0x03040506);
1060        assert_eq!(rtp.ssrc(), 0x0708090a);
1061        let mut csrc = rtp.csrc();
1062        assert_eq!(csrc.next(), Some(0x0b0c0d0e));
1063        assert_eq!(csrc.next(), None);
1064        let (ext_id, ext_data) = rtp.extension().unwrap();
1065        assert_eq!(ext_id, 0x9876);
1066        assert_eq!(ext_data, extension_data.0);
1067        assert_eq!(rtp.payload(), payload_data.0);
1068    }
1069
1070    #[test]
1071    fn write_rtp_vec_with_clear() {
1072        let mut vec = vec![];
1073        let payload_data = [1, 2, 3, 4, 5, 6, 7, 8];
1074        let builder = RtpPacketBuilder::new()
1075            .payload_type(96)
1076            .payload(payload_data.as_ref());
1077        let mut writer = RtpPacketWriterMutVec::new(&mut vec);
1078        builder.write(&mut writer).unwrap();
1079        assert_eq!(writer.len(), 20);
1080        let data = writer.as_ref();
1081        println!("{data:?}");
1082        let rtp = RtpPacket::parse(data).unwrap();
1083        assert_eq!(rtp.version(), 2);
1084        assert_eq!(rtp.payload_type(), 96);
1085        assert_eq!(rtp.payload(), payload_data);
1086        writer.clear();
1087        let payload2 = [9, 10, 11];
1088        let builder = builder.clear_payloads().payload(payload2.as_ref());
1089        builder.write(&mut writer).unwrap();
1090        assert_eq!(writer.len(), 15);
1091        let data = writer.as_ref();
1092        println!("{data:?}");
1093        let rtp = RtpPacket::parse(data).unwrap();
1094        assert_eq!(rtp.version(), 2);
1095        assert_eq!(rtp.payload_type(), 96);
1096        assert_eq!(rtp.payload(), payload2);
1097    }
1098}