use bytes::{Buf, BufMut, Bytes, BytesMut};
use crate::InvalidInput;
#[repr(packed)]
struct RawRtpHeader {
options: u16,
sequence_number: u16,
timestamp: u32,
ssrc: u32,
}
#[derive(Clone)]
pub struct RtpHeader {
options: u16,
sequence_number: u16,
timestamp: u32,
ssrc: u32,
csrcs: Vec<u32>,
extension: Option<RtpHeaderExtension>,
}
impl RtpHeader {
#[inline]
pub const fn new() -> Self {
Self {
options: 2 << 14,
sequence_number: 0,
timestamp: 0,
ssrc: 0,
csrcs: Vec::new(),
extension: None,
}
}
pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
let mut buffer = data.clone();
if buffer.len() < std::mem::size_of::<RawRtpHeader>() {
return Err(InvalidInput);
}
let ptr = buffer.as_ptr() as *const RawRtpHeader;
let raw = unsafe { &*ptr };
let mut res = Self {
options: u16::from_be(raw.options),
sequence_number: u16::from_be(raw.sequence_number),
timestamp: u32::from_be(raw.timestamp),
ssrc: u32::from_be(raw.ssrc),
csrcs: Vec::new(),
extension: None,
};
buffer.advance(std::mem::size_of::<RawRtpHeader>());
if (res.options >> 14) != 2 {
return Err(InvalidInput);
}
let csrc_count = ((res.options >> 8) & 0xf) as usize;
if buffer.len() < (csrc_count << 2) {
return Err(InvalidInput);
}
res.csrcs = Vec::with_capacity(csrc_count);
for _ in 0..csrc_count {
res.csrcs.push(buffer.get_u32());
}
if (res.options & 0x1000) != 0 {
res.extension = Some(RtpHeaderExtension::decode(&mut buffer)?);
}
*data = buffer;
Ok(res)
}
pub fn encode(&self, buf: &mut BytesMut) {
buf.reserve(self.raw_size());
let raw = RawRtpHeader {
options: self.options.to_be(),
sequence_number: self.sequence_number.to_be(),
timestamp: self.timestamp.to_be(),
ssrc: self.ssrc.to_be(),
};
let ptr = &raw as *const _ as *const u8;
let data = unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawRtpHeader>()) };
buf.extend_from_slice(data);
for csrc in &self.csrcs {
buf.put_u32(*csrc);
}
if let Some(extension) = self.extension.as_ref() {
extension.encode(buf);
}
}
#[inline]
pub fn padding(&self) -> bool {
(self.options & 0x2000) != 0
}
#[inline]
pub fn with_padding(mut self, padding: bool) -> Self {
self.options &= !0x2000;
self.options |= (padding as u16) << 13;
self
}
#[inline]
pub fn extension(&self) -> Option<&RtpHeaderExtension> {
self.extension.as_ref()
}
#[inline]
pub fn with_extension(mut self, extension: Option<RtpHeaderExtension>) -> Self {
self.options &= !0x1000;
self.options |= (extension.is_some() as u16) << 12;
self.extension = extension;
self
}
#[inline]
pub fn marker(&self) -> bool {
(self.options & 0x0080) != 0
}
#[inline]
pub fn with_marker(mut self, marker: bool) -> Self {
self.options &= !0x0080;
self.options |= (marker as u16) << 7;
self
}
#[inline]
pub fn payload_type(&self) -> u8 {
(self.options & 0x7f) as u8
}
#[inline]
pub fn with_payload_type(mut self, payload_type: u8) -> Self {
assert!(payload_type < 128);
self.options &= !0x7f;
self.options |= (payload_type & 0x7f) as u16;
self
}
#[inline]
pub fn sequence_number(&self) -> u16 {
self.sequence_number
}
#[inline]
pub fn with_sequence_number(mut self, n: u16) -> Self {
self.sequence_number = n;
self
}
#[inline]
pub fn timestamp(&self) -> u32 {
self.timestamp
}
#[inline]
pub fn with_timestamp(mut self, timestamp: u32) -> Self {
self.timestamp = timestamp;
self
}
#[inline]
pub fn ssrc(&self) -> u32 {
self.ssrc
}
#[inline]
pub fn with_ssrc(mut self, ssrc: u32) -> Self {
self.ssrc = ssrc;
self
}
#[inline]
pub fn csrcs(&self) -> &[u32] {
&self.csrcs
}
#[inline]
pub fn with_csrcs<T>(mut self, csrcs: T) -> Self
where
T: Into<Vec<u32>>,
{
let csrcs = csrcs.into();
assert!(csrcs.len() <= 0xf);
self.csrcs = csrcs;
self.options &= !0xf00;
self.options |= (self.csrcs.len() as u16) << 8;
self
}
#[inline]
pub fn raw_size(&self) -> usize {
std::mem::size_of::<RawRtpHeader>()
+ (self.csrcs.len() << 2)
+ self.extension.as_ref().map(|e| e.raw_size()).unwrap_or(0)
}
}
impl Default for RtpHeader {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[repr(packed)]
struct RawHeaderExtension {
misc: u16,
length: u16,
}
#[derive(Clone)]
pub struct RtpHeaderExtension {
misc: u16,
data: Bytes,
}
impl RtpHeaderExtension {
#[inline]
pub const fn new() -> Self {
Self {
misc: 0,
data: Bytes::new(),
}
}
pub fn decode(data: &mut Bytes) -> Result<Self, InvalidInput> {
let mut buffer = data.clone();
if buffer.len() < std::mem::size_of::<RawHeaderExtension>() {
return Err(InvalidInput);
}
let ptr = buffer.as_ptr() as *const RawHeaderExtension;
let raw = unsafe { &*ptr };
let extension_length = (u16::from_be(raw.length) as usize) << 2;
let misc = u16::from_be(raw.misc);
buffer.advance(std::mem::size_of::<RawHeaderExtension>());
if buffer.len() < extension_length {
return Err(InvalidInput);
}
let res = Self {
misc,
data: buffer.split_to(extension_length),
};
*data = buffer;
Ok(res)
}
pub fn encode(&self, buf: &mut BytesMut) {
buf.reserve(self.raw_size());
let length = (self.data.len() >> 2) as u16;
let raw = RawHeaderExtension {
misc: self.misc.to_be(),
length: length.to_be(),
};
let ptr = &raw as *const _ as *const u8;
let header =
unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::<RawHeaderExtension>()) };
buf.extend_from_slice(header);
buf.extend_from_slice(&self.data);
}
#[inline]
pub fn misc(&self) -> u16 {
self.misc
}
#[inline]
pub fn with_misc(mut self, misc: u16) -> Self {
self.misc = misc;
self
}
#[inline]
pub fn data(&self) -> &Bytes {
&self.data
}
#[inline]
pub fn with_data(mut self, data: Bytes) -> Self {
assert_eq!(data.len() & 3, 0);
let words = data.len() >> 2;
assert!(words <= (u16::MAX as usize));
self.data = data;
self
}
#[inline]
pub fn raw_size(&self) -> usize {
std::mem::size_of::<RawHeaderExtension>() + self.data.len()
}
}
impl Default for RtpHeaderExtension {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
pub struct RtpPacket {
header: RtpHeader,
payload: Bytes,
}
impl RtpPacket {
#[inline]
pub const fn new() -> Self {
Self {
header: RtpHeader::new(),
payload: Bytes::new(),
}
}
pub fn from_parts(header: RtpHeader, payload: Bytes) -> Result<Self, InvalidInput> {
if header.padding() {
let padding_len = payload.last().copied().ok_or(InvalidInput)? as usize;
if padding_len == 0 || payload.len() < padding_len {
return Err(InvalidInput);
}
}
let res = Self { header, payload };
Ok(res)
}
#[inline]
pub fn deconstruct(self) -> (RtpHeader, Bytes) {
(self.header, self.payload)
}
pub fn decode(mut frame: Bytes) -> Result<Self, InvalidInput> {
let header = RtpHeader::decode(&mut frame)?;
let payload = frame;
Self::from_parts(header, payload)
}
pub fn encode(&self, buf: &mut BytesMut) {
buf.reserve(self.raw_size());
self.header.encode(buf);
buf.extend_from_slice(&self.payload);
}
#[inline]
pub fn header(&self) -> &RtpHeader {
&self.header
}
#[inline]
pub fn marker(&self) -> bool {
self.header.marker()
}
#[inline]
pub fn with_marker(mut self, marker: bool) -> Self {
self.header = self.header.with_marker(marker);
self
}
#[inline]
pub fn payload_type(&self) -> u8 {
self.header.payload_type()
}
#[inline]
pub fn with_payload_type(mut self, payload_type: u8) -> Self {
self.header = self.header.with_payload_type(payload_type);
self
}
#[inline]
pub fn sequence_number(&self) -> u16 {
self.header.sequence_number()
}
#[inline]
pub fn with_sequence_number(mut self, sequence_number: u16) -> Self {
self.header = self.header.with_sequence_number(sequence_number);
self
}
#[inline]
pub fn timestamp(&self) -> u32 {
self.header.timestamp()
}
#[inline]
pub fn with_timestamp(mut self, timestamp: u32) -> Self {
self.header = self.header.with_timestamp(timestamp);
self
}
#[inline]
pub fn ssrc(&self) -> u32 {
self.header.ssrc()
}
#[inline]
pub fn with_ssrc(mut self, ssrc: u32) -> Self {
self.header = self.header.with_ssrc(ssrc);
self
}
#[inline]
pub fn csrcs(&self) -> &[u32] {
self.header.csrcs()
}
#[inline]
pub fn with_csrcs<T>(mut self, csrcs: T) -> Self
where
T: Into<Vec<u32>>,
{
self.header = self.header.with_csrcs(csrcs);
self
}
#[inline]
pub fn padding(&self) -> u8 {
if self.header.padding() {
*self.payload.last().unwrap()
} else {
0
}
}
#[inline]
pub fn payload(&self) -> &Bytes {
&self.payload
}
#[inline]
pub fn stripped_payload(&self) -> Bytes {
let payload_len = self.payload.len();
let padding_len = self.padding() as usize;
let len = payload_len - padding_len;
self.payload.slice(..len)
}
#[inline]
pub fn with_payload(mut self, payload: Bytes, padding: u8) -> Self {
if padding > 0 {
let len = payload.len() + (padding as usize);
let mut buffer = BytesMut::with_capacity(len);
buffer.extend_from_slice(&payload);
buffer.resize(len, 0);
buffer[len - 1] = padding;
self.header = self.header.with_padding(true);
self.payload = buffer.freeze();
} else {
self.header = self.header.with_padding(false);
self.payload = payload;
}
self
}
#[inline]
pub fn with_padded_payload(mut self, payload: Bytes) -> Self {
let padding_len = payload.last().copied().expect("empty payload") as usize;
assert!(padding_len > 0 && payload.len() >= padding_len);
self.header = self.header.with_padding(true);
self.payload = payload;
self
}
#[inline]
pub fn raw_size(&self) -> usize {
self.header.raw_size() + self.payload.len()
}
}
impl Default for RtpPacket {
#[inline]
fn default() -> Self {
Self::new()
}
}