diff --git a/src/builder.rs b/src/builder.rs index 21ff0c8..f4ceb9a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::marker::PhantomData; + use crate::RtpPacket; /// Errors produced when wrting a packet @@ -27,13 +29,13 @@ pub enum RtpWriteError { InvalidPadding, } -/// Struct for building a new RTP packet +/// Struct for building a new RTP packet. #[derive(Debug)] #[must_use = "The builder must be built to be used"] pub struct RtpPacketBuilder { padding: Option, csrcs: smallvec::SmallVec<[u32; 15]>, - marker: bool, + marker_bit: bool, payload_type: u8, sequence_number: u16, timestamp: u32, @@ -49,12 +51,12 @@ impl Default for RtpPacketBuilder { } impl RtpPacketBuilder { - /// Construct a new packet builder + /// Construct a new packet builder. pub fn new() -> RtpPacketBuilder { Self { padding: None, csrcs: smallvec::smallvec![], - marker: false, + marker_bit: false, // set to an invalid value to force the user to update payload_type: 0xff, sequence_number: 0, @@ -65,67 +67,73 @@ impl RtpPacketBuilder { } } - /// Set the number of padding bytes to use for this packet + /// Set the number of padding bytes to use for this packet. pub fn padding(mut self, padding: u8) -> Self { self.padding = Some(padding); self } - /// Set 1. whether padding is used and 2. the number of padding bytes to use for this packet + /// Set 1. whether padding is used and 2. the number of padding bytes to use for this packet. pub fn maybe_padding(mut self, padding: Option) -> Self { self.padding = padding; self } - /// Add a Contribution Source for this packet + /// Add a Contribution Source for this packet. pub fn add_csrc(mut self, csrc: u32) -> Self { self.csrcs.push(csrc); self } - /// Clear any CSRCs configured for this packet + /// Clear any CSRCs configured for this packet. pub fn clear_csrcs(mut self) -> Self { self.csrcs.clear(); self } - /// Set the marker bit for this packet - pub fn marker(mut self, marker: bool) -> Self { - self.marker = marker; + /// Set the marker bit for this packet. + #[deprecated = "Use `marker_bit()` instead"] + pub fn marker(self, marker: bool) -> Self { + self.marker_bit(marker) + } + + /// Set the marker bit for this packet. + pub fn marker_bit(mut self, marker_bit: bool) -> Self { + self.marker_bit = marker_bit; self } - /// Set the payload type for this packet + /// Set the payload type for this packet. pub fn payload_type(mut self, pt: u8) -> Self { self.payload_type = pt; self } - /// Set the sequence number for this packet + /// Set the sequence number for this packet. pub fn sequence_number(mut self, sequence: u16) -> Self { self.sequence_number = sequence; self } - /// Set the RTP timestamp for this packet + /// Set the RTP timestamp for this packet. pub fn timestamp(mut self, timestamp: u32) -> Self { self.timestamp = timestamp; self } - /// Set the Sequence source for this packet + /// Set the Sequence source for this packet. pub fn ssrc(mut self, ssrc: u32) -> Self { self.ssrc = ssrc; self } - /// Set the extension header for this packet + /// Set the extension header for this packet. pub fn extension(mut self, extension_id: u16, extension_data: E) -> Self { self.extension = Some((extension_id, extension_data)); self } - /// Clear any extension data configured for this packet + /// Clear any extension data configured for this packet. pub fn clear_extension(mut self) -> Self { self.extension = None; self @@ -140,7 +148,7 @@ impl RtpPacketBuilder { self } - /// Clear any payloads currently configured + /// Clear any payloads currently configured. pub fn clear_payloads(mut self) -> Self { self.payloads.clear(); self @@ -182,7 +190,7 @@ impl RtpPacketBuilder { buf[0] = byte; let mut byte = self.payload_type & 0x7f; - if self.marker { + if self.marker_bit { byte |= 0x80; } buf[1] = byte; @@ -220,7 +228,7 @@ impl RtpPacketBuilder { self.calculate_size() } - /// Write this packet using writer without any validity checks + /// Write this packet using writer without any validity checks. pub fn write_unchecked( &self, writer: &mut impl RtpPacketWriter, @@ -267,30 +275,30 @@ impl RtpPacketBuilder { } } -impl<'a> RtpPacketBuilder<&'a [u8], &'a [u8]> { +impl<'a, 'b> RtpPacketBuilder<&'a [u8], &'b [u8]> { /// Write this packet into `buf` without any validity checks. Returns the number of bytes /// written. - pub fn write_into_unchecked<'b: 'a>(&self, buf: &'b mut [u8]) -> usize { + pub fn write_into_unchecked(&self, buf: &mut [u8]) -> usize { let mut writer = RtpPacketWriterMutSlice::new(buf); self.write_unchecked(&mut writer) } /// Write this packet into `buf`. On success returns the number of bytes written or an /// `RtpWriteError` on failure. - pub fn write_into<'b: 'a>(&self, buf: &'b mut [u8]) -> Result { + pub fn write_into(&self, buf: &mut [u8]) -> Result { let mut writer = RtpPacketWriterMutSlice::new(buf); self.write(&mut writer) } /// Write this packet into `buf` without any validity checks. The data will be appended to the /// end of the provide Vec. - pub fn write_into_vec_unchecked(&self, buf: &'a mut Vec) { + pub fn write_into_vec_unchecked(&self, buf: &mut Vec) { let mut writer = RtpPacketWriterMutVec::new(buf); self.write_unchecked(&mut writer) } /// Write this packet into `buf`. The data will be appended to the end of the provide Vec. - pub fn write_into_vec(&self, buf: &'a mut Vec) -> Result<(), RtpWriteError> { + pub fn write_into_vec(&self, buf: &mut Vec) -> Result<(), RtpWriteError> { let mut writer = RtpPacketWriterMutVec::new(buf); self.write(&mut writer) } @@ -308,7 +316,7 @@ impl<'a> RtpPacketBuilder<&'a [u8], &'a [u8]> { } } -/// Trait to provide the length of a piece of data in bytes +/// Trait to provide the length of a piece of data in bytes. pub trait PayloadLength { fn len(&self) -> usize; fn is_empty(&self) -> bool { @@ -316,14 +324,14 @@ pub trait PayloadLength { } } -/// Trait to write an RTP packet into and/or from custom data types +/// Trait to write an RTP packet into and/or from custom data types. pub trait RtpPacketWriter { type Output; type Payload: PayloadLength; type Extension: PayloadLength; /// Reserve a number of bytes in the output. Multiple calls are possible and provide the - /// entire size to reserve + /// entire size to reserve. fn reserve(&mut self, _size: usize) {} /// Return the maximum size of the output. If the output data is not bound to a fixed size, @@ -340,7 +348,7 @@ pub trait RtpPacketWriter { fn push_extension(&mut self, extension_data: &Self::Extension); /// Provides the payload data to add to the output. The payload should be written as-is - /// without any transformations + /// without any transformations. fn push_payload(&mut self, payload: &Self::Payload); /// Provides any padding value the builder was constructed with. The padding value specifies @@ -379,18 +387,18 @@ impl PayloadLength for &[T; N] { } } -/// An implementation of a [`RtpPacketWriter`] that appends to a `Vec` +/// An implementation of a [`RtpPacketWriter`] that appends to a `Vec`. #[derive(Default, Debug)] -pub struct RtpPacketWriterVec<'a> { +pub struct RtpPacketWriterVec<'a, 'b> { output: Vec, padding: Option, - phantom: std::marker::PhantomData<&'a [u8]>, + phantom: PhantomData<(&'a [u8], &'b [u8])>, } -impl<'a> RtpPacketWriter for RtpPacketWriterVec<'a> { +impl<'a, 'b> RtpPacketWriter for RtpPacketWriterVec<'a, 'b> { type Output = Vec; type Payload = &'a [u8]; - type Extension = &'a [u8]; + type Extension = &'b [u8]; fn reserve(&mut self, size: usize) { if self.output.len() < size { @@ -429,23 +437,25 @@ impl<'a> RtpPacketWriter for RtpPacketWriterVec<'a> { /// An implementation of a [`RtpPacketWriter`] that writes to a `&mut [u8]`. Each packet will be /// written starting at the beginning of the provided slice. #[derive(Default, Debug)] -pub struct RtpPacketWriterMutSlice<'a> { +pub struct RtpPacketWriterMutSlice<'a, 'b, 'c> { output: &'a mut [u8], padding: Option, write_i: usize, + phantom: PhantomData<(&'b [u8], &'c [u8])>, } -impl<'a> RtpPacketWriterMutSlice<'a> { +impl<'a, 'b, 'c> RtpPacketWriterMutSlice<'a, 'b, 'c> { pub fn new(buf: &'a mut [u8]) -> Self { Self { output: buf, padding: None, write_i: 0, + phantom: PhantomData, } } } -impl<'a> std::ops::Deref for RtpPacketWriterMutSlice<'a> { +impl<'a, 'b, 'c> std::ops::Deref for RtpPacketWriterMutSlice<'a, 'b, 'c> { type Target = [u8]; fn deref(&self) -> &Self::Target { @@ -453,16 +463,16 @@ impl<'a> std::ops::Deref for RtpPacketWriterMutSlice<'a> { } } -impl<'a> std::ops::DerefMut for RtpPacketWriterMutSlice<'a> { +impl<'a, 'b, 'c> std::ops::DerefMut for RtpPacketWriterMutSlice<'a, 'b, 'c> { fn deref_mut(&mut self) -> &mut Self::Target { self.output } } -impl<'a> RtpPacketWriter for RtpPacketWriterMutSlice<'a> { +impl<'a, 'b, 'c> RtpPacketWriter for RtpPacketWriterMutSlice<'a, 'b, 'c> { type Output = usize; - type Payload = &'a [u8]; - type Extension = &'a [u8]; + type Payload = &'b [u8]; + type Extension = &'c [u8]; fn max_size(&self) -> Option { Some(self.output.len()) @@ -503,21 +513,23 @@ impl<'a> RtpPacketWriter for RtpPacketWriterMutSlice<'a> { /// written will be appended to the provide `Vec`. You can `clear()` the vec in between packets /// to have each packet written from the beginning of the vec. #[derive(Debug)] -pub struct RtpPacketWriterMutVec<'a> { +pub struct RtpPacketWriterMutVec<'a, 'b, 'c> { output: &'a mut Vec, padding: Option, + phantom: PhantomData<(&'b [u8], &'c [u8])>, } -impl<'a> RtpPacketWriterMutVec<'a> { +impl<'a, 'b, 'c> RtpPacketWriterMutVec<'a, 'b, 'c> { pub fn new(buf: &'a mut Vec) -> Self { Self { output: buf, padding: None, + phantom: PhantomData, } } } -impl<'a> std::ops::Deref for RtpPacketWriterMutVec<'a> { +impl<'a, 'b, 'c> std::ops::Deref for RtpPacketWriterMutVec<'a, 'b, 'c> { type Target = Vec; fn deref(&self) -> &Self::Target { @@ -525,16 +537,16 @@ impl<'a> std::ops::Deref for RtpPacketWriterMutVec<'a> { } } -impl<'a> std::ops::DerefMut for RtpPacketWriterMutVec<'a> { +impl<'a, 'b, 'c> std::ops::DerefMut for RtpPacketWriterMutVec<'a, 'b, 'c> { fn deref_mut(&mut self) -> &mut Self::Target { self.output } } -impl<'a> RtpPacketWriter for RtpPacketWriterMutVec<'a> { +impl<'a, 'b, 'c> RtpPacketWriter for RtpPacketWriterMutVec<'a, 'b, 'c> { type Output = (); - type Payload = &'a [u8]; - type Extension = &'a [u8]; + type Payload = &'b [u8]; + type Extension = &'c [u8]; fn push(&mut self, data: &[u8]) { self.output.extend(data); @@ -583,7 +595,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0); assert_eq!(rtp.timestamp(), 0x0); @@ -600,7 +612,7 @@ mod tests { let mut vec = vec![]; let builder = RtpPacketBuilder::new() .payload_type(96) - .marker(true) + .marker_bit(true) .sequence_number(0x0102) .timestamp(0x03040506) .ssrc(0x0708090a) @@ -618,7 +630,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 1); - assert!(rtp.marker()); + assert!(rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -692,7 +704,7 @@ mod tests { let extension_data = [1, 2, 3, 4, 5, 6, 7, 8]; let builder = RtpPacketBuilder::new() .payload_type(96) - .marker(true) + .marker_bit(true) .sequence_number(0x0102) .timestamp(0x03040506) .ssrc(0x0708090a) @@ -711,7 +723,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 1); - assert!(rtp.marker()); + assert!(rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -732,7 +744,7 @@ mod tests { let payload_data = [1, 2, 3, 4, 5, 6, 7, 8]; let builder = RtpPacketBuilder::new() .payload_type(96) - .marker(true) + .marker_bit(true) .sequence_number(0x0102) .timestamp(0x03040506) .ssrc(0x0708090a) @@ -753,7 +765,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), Some(7)); assert_eq!(rtp.n_csrcs(), 1); - assert!(rtp.marker()); + assert!(rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -1005,7 +1017,7 @@ mod tests { let payload_data = TestPayload(vec![11, 12, 13, 14, 15, 16, 17, 18]); let builder = RtpPacketBuilder::new() .payload_type(96) - .marker(true) + .marker_bit(true) .sequence_number(0x0102) .timestamp(0x03040506) .ssrc(0x0708090a) @@ -1022,7 +1034,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), Some(7)); assert_eq!(rtp.n_csrcs(), 1); - assert!(rtp.marker()); + assert!(rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); diff --git a/src/edit.rs b/src/edit.rs index fdb2ff5..e5ea493 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -2,7 +2,7 @@ use crate::{RtpPacket, RtpParseError, RtpWriteError}; -/// Packet editing +/// Mutable parsed RTP packet for editing of some fields. #[repr(transparent)] pub struct RtpPacketMut<'a> { data: &'a mut [u8], @@ -18,7 +18,7 @@ impl<'a> std::ops::Deref for RtpPacketMut<'a> { } impl<'a> RtpPacketMut<'a> { - /// The minimum number of bytes a RTP packet must be to be parsed correctly + /// The minimum number of bytes a RTP packet must be to be parsed correctly. pub const MIN_RTP_PACKET_LEN: usize = RtpPacket::MIN_RTP_PACKET_LEN; /// Parse a byte slice into an editable [`RtpPacketMut`]. The packet is first parsed using @@ -29,16 +29,22 @@ impl<'a> RtpPacketMut<'a> { Ok(RtpPacketMut { data }) } - /// Change the marker bit of this packet + /// Change the marker bit of this packet. + #[deprecated = "Use `set_marker_bit()` instead"] pub fn set_marker(&mut self, marker: bool) { - if marker { + self.set_marker_bit(marker); + } + + /// Change the marker bit of this packet. + pub fn set_marker_bit(&mut self, marker_bit: bool) { + if marker_bit { self.data[1] |= 0x80; } else { self.data[1] &= 0x7f; } } - /// Change the payload type of this packet + /// Change the payload type of this packet. pub fn set_payload_type(&mut self, pt: u8) -> Result<(), RtpWriteError> { if pt > 0x7f { return Err(RtpWriteError::InvalidPayloadType(pt)); @@ -49,13 +55,13 @@ impl<'a> RtpPacketMut<'a> { Ok(()) } - /// Change the sequence number of this packet + /// Change the sequence number of this packet. pub fn set_sequence_number(&mut self, sequence: u16) { self.data[2] = (sequence >> 8) as u8; self.data[3] = (sequence & 0xff) as u8; } - /// Change the timestamp of this packet + /// Change the timestamp of this packet. pub fn set_timestamp(&mut self, timestamp: u32) { self.data[4] = (timestamp >> 24) as u8; self.data[5] = ((timestamp >> 16) & 0xff) as u8; @@ -63,13 +69,44 @@ impl<'a> RtpPacketMut<'a> { self.data[7] = (timestamp & 0xff) as u8; } - /// Change the SSRC of this packet + /// Change the SSRC of this packet. pub fn set_ssrc(&mut self, ssrc: u32) { self.data[8] = (ssrc >> 24) as u8; self.data[9] = ((ssrc >> 16) & 0xff) as u8; self.data[10] = ((ssrc >> 8) & 0xff) as u8; self.data[11] = (ssrc & 0xff) as u8; } + + /// Change the extension identifier of this packet. + /// + /// This has no effect if the packet does not contain any extension data. + pub fn set_extension_id(&mut self, id: u16) { + if self.extension_bit() { + let offset = self.extension_offset(); + self.data[offset] = (id >> 8) as u8; + self.data[offset + 1] = (id & 0xff) as u8; + } + } + + /// Returns a mutable reference to the extension data for this packet, if any. + pub fn extension_mut(&mut self) -> Option<&mut [u8]> { + if self.extension_bit() { + let offset = self.extension_offset(); + let offset = offset + 4; + let len = self.extension_len(); + Some(&mut self.data[offset..][..len]) + } else { + None + } + } + + /// Returns a mutable reference to the payload data of this packet. + pub fn payload_mut(&mut self) -> &mut [u8] { + let offset = self.payload_offset(); + let pad = self.padding().unwrap_or_default() as usize; + let data_len = self.data.len(); + &mut self.data[offset..data_len - pad] + } } #[cfg(test)] @@ -85,7 +122,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -93,8 +130,8 @@ mod tests { assert_eq!(rtp.csrc().count(), 0); assert_eq!(rtp.extension(), None); assert_eq!(rtp.payload(), &[]); - rtp.set_marker(true); - assert!(rtp.marker()); + rtp.set_marker_bit(true); + assert!(rtp.marker_bit()); rtp.set_payload_type(12).unwrap(); assert_eq!(rtp.payload_type(), 12); rtp.set_sequence_number(0x9876); diff --git a/src/packet.rs b/src/packet.rs index 37f1223..784a1ad 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -2,26 +2,26 @@ use std::fmt; -/// An error produced when parsing a packet +/// An error produced when parsing a packet. #[derive(Debug, thiserror::Error)] pub enum RtpParseError { - /// Version is unsupported. This implementation only supports version 2 + /// Version is unsupported. This implementation only supports version 2. #[error("Unsupported RTP version {}", .0)] UnsupportedVersion(u8), /// There is not enough data available to successfully parse the packet #[error("Not enough data available to parse the packet: expected {}, actual {}", .expected, .actual)] Truncated { - /// The expected size + /// The expected size. expected: usize, - /// The actual size encountered + /// The actual size encountered. actual: usize, }, - /// The padding byte does not contain a valid value + /// The padding byte does not contain a valid value. #[error("Padding contains invalid value {}", .0)] PaddingInvalid(u8), } -/// A parsed RTP packet. A wrapper around a byte slice. Each field is only accessed when needed +/// A parsed RTP packet. A wrapper around a byte slice. Each field is only accessed when needed. #[repr(transparent)] pub struct RtpPacket<'a> { data: &'a [u8], @@ -45,7 +45,7 @@ impl<'a> fmt::Debug for RtpPacket<'a> { f.debug_struct("RtpPacket") .field("version", &self.version()) - .field("marker", &self.marker()) + .field("marker_bit", &self.marker_bit()) .field("payload_type", &self.payload_type()) .field("sequence_number", &self.sequence_number()) .field("timestamp", &self.timestamp()) @@ -59,10 +59,10 @@ impl<'a> fmt::Debug for RtpPacket<'a> { } impl<'a> RtpPacket<'a> { - /// The minimum number of bytes a RTP packet must be to be parsed correctly + /// The minimum number of bytes a RTP packet must be to be parsed correctly. pub const MIN_RTP_PACKET_LEN: usize = 12; - /// The maximum number of CSRCs a RTP packet can contain + /// The maximum number of CSRCs a RTP packet can contain. pub const MAX_N_CSRCS: usize = 0xf; /// Parse a byte slice into a [`RtpPacket`]. This implementation prefers to fail fast and will @@ -141,11 +141,12 @@ impl<'a> RtpPacket<'a> { (self.data[0] & 0b1100_0000) >> 6 } - fn padding_bit(&self) -> bool { + /// Returns whether the padding bit is set for this packet. + pub fn padding_bit(&self) -> bool { self.data[0] & 0b0010_0000 != 0 } - /// Returns the number of bytes of padding used by this packet or `None` + /// Returns the number of bytes of padding used by this packet or `None`. pub fn padding(&self) -> Option { if self.padding_bit() { Some(self.data[self.data.len() - 1]) @@ -154,7 +155,8 @@ impl<'a> RtpPacket<'a> { } } - fn extension_bit(&self) -> bool { + /// Returns whether the extension bit is set for this packet. + pub fn extension_bit(&self) -> bool { (self.data[0] & 0b0001_0000) != 0 } @@ -165,8 +167,15 @@ impl<'a> RtpPacket<'a> { } /// Returns whether the marker bit is set for this packet. The meaning of the marker bit - /// is payload-specific + /// is payload-specific. + #[deprecated = "Use `marker_bit()` instead"] pub fn marker(&self) -> bool { + self.marker_bit() + } + + /// Returns whether the marker bit is set for this packet. The meaning of the marker bit + /// is payload-specific. + pub fn marker_bit(&self) -> bool { (self.data[1] & 0b1000_0000) != 0 } @@ -175,7 +184,7 @@ impl<'a> RtpPacket<'a> { self.data[1] & 0b0111_1111 } - /// Returns the sequence number for this packet + /// Returns the sequence number for this packet. pub fn sequence_number(&self) -> u16 { (self.data[2] as u16) << 8 | self.data[3] as u16 } @@ -188,7 +197,7 @@ impl<'a> RtpPacket<'a> { | (self.data[7] as u32) } - /// Returns the Sychronisation Source for this packet + /// Returns the Sychronisation Source for this packet. pub fn ssrc(&self) -> u32 { (self.data[8] as u32) << 24 | (self.data[9] as u32) << 16 @@ -196,7 +205,7 @@ impl<'a> RtpPacket<'a> { | (self.data[11] as u32) } - /// Returns a (potentially empty) iterator over the Contribution Sources for this packet + /// Returns a (potentially empty) iterator over the Contribution Sources for this packet. pub fn csrc(&self) -> impl Iterator + '_ { self.data[Self::MIN_RTP_PACKET_LEN..] .chunks_exact(4) @@ -209,11 +218,12 @@ impl<'a> RtpPacket<'a> { }) } - fn extension_offset(&self) -> usize { + pub(crate) fn extension_offset(&self) -> usize { Self::MIN_RTP_PACKET_LEN + (self.n_csrcs() as usize) * 4 } - fn extension_len(&self) -> usize { + /// Returns the length of the extension data in this packet. + pub fn extension_len(&self) -> usize { if self.extension_bit() { let offset = self.extension_offset(); 4 * ((self.data[offset + 2] as usize) << 8 | self.data[offset + 3] as usize) @@ -229,13 +239,14 @@ impl<'a> RtpPacket<'a> { let offset = self.extension_offset(); let id = (self.data[offset] as u16) << 8 | self.data[offset + 1] as u16; let offset = offset + 4; - Some((id, &self.data[offset..offset + self.extension_len()])) + Some((id, &self.data[offset..][..self.extension_len()])) } else { None } } - fn payload_offset(&self) -> usize { + /// Returns the offset of the payload in this packet relative to the beginning of the packet. + pub fn payload_offset(&self) -> usize { self.extension_offset() + if self.extension_bit() { self.extension_len() + 4 @@ -244,14 +255,18 @@ impl<'a> RtpPacket<'a> { } } - /// Returns the payload data + /// Returns the length of the payload in this packet without padding. + pub fn payload_len(&self) -> usize { + let offset = self.payload_offset(); + let pad = self.padding().unwrap_or_default() as usize; + + self.data.len() - pad - offset + } + + /// Returns the payload data. pub fn payload(&self) -> &[u8] { let offset = self.payload_offset(); - let pad = if let Some(pad) = self.padding() { - pad as usize - } else { - 0 - }; + let pad = self.padding().unwrap_or_default() as usize; &self.data[offset..self.data.len() - pad] } @@ -259,7 +274,7 @@ impl<'a> RtpPacket<'a> { /// any padding bytes). Any aspect of the returned builder can be modified. pub fn as_builder(&'a self) -> crate::RtpPacketBuilder<&'a [u8], &'a [u8]> { let mut builder = crate::RtpPacketBuilder::new() - .marker(self.marker()) + .marker_bit(self.marker_bit()) .payload_type(self.payload_type()) .sequence_number(self.sequence_number()) .timestamp(self.timestamp()) @@ -291,7 +306,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -327,7 +342,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 1); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -366,7 +381,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -421,7 +436,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), None); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506); @@ -443,7 +458,7 @@ mod tests { assert_eq!(rtp.version(), 2); assert_eq!(rtp.padding(), Some(2)); assert_eq!(rtp.n_csrcs(), 0); - assert!(!rtp.marker()); + assert!(!rtp.marker_bit()); assert_eq!(rtp.payload_type(), 96); assert_eq!(rtp.sequence_number(), 0x0102); assert_eq!(rtp.timestamp(), 0x03040506);