use std::{borrow::Borrow, ops::Deref, time::Instant};
use bytes::{Buf, BufMut, Bytes, BytesMut};
use zerocopy::{
byteorder::network_endian::{U16, U32},
FromBytes, Immutable, IntoBytes, KnownLayout, SizeError, Unaligned,
};
use crate::InvalidInput;
#[derive(Copy, Clone, KnownLayout, Immutable, Unaligned, IntoBytes, FromBytes)]
#[repr(C)]
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();
let (raw, _) = RawRtpHeader::ref_from_prefix(&buffer)
.map_err(SizeError::from)
.map_err(|_| InvalidInput::new())?;
let mut res = Self {
options: raw.options.get(),
sequence_number: raw.sequence_number.get(),
timestamp: raw.timestamp.get(),
ssrc: raw.ssrc.get(),
csrcs: Vec::new(),
extension: None,
};
buffer.advance(std::mem::size_of::<RawRtpHeader>());
if (res.options >> 14) != 2 {
return Err(InvalidInput::new());
}
let csrc_count = ((res.options >> 8) & 0xf) as usize;
let (csrcs, _) = <[U32]>::ref_from_prefix_with_elems(&buffer, csrc_count)
.map_err(SizeError::from)
.map_err(|_| InvalidInput::new())?;
res.csrcs = csrcs.iter().copied().map(U32::get).collect();
buffer.advance(csrc_count << 2);
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: U16::new(self.options),
sequence_number: U16::new(self.sequence_number),
timestamp: U32::new(self.timestamp),
ssrc: U32::new(self.ssrc),
};
buf.extend_from_slice(raw.as_bytes());
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
}
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
}
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()
}
}
#[derive(Copy, Clone, KnownLayout, Immutable, Unaligned, IntoBytes, FromBytes)]
#[repr(C)]
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();
let (raw, _) = RawHeaderExtension::ref_from_prefix(&buffer)
.map_err(SizeError::from)
.map_err(|_| InvalidInput::new())?;
let extension_length = (raw.length.get() as usize) << 2;
let misc = raw.misc.get();
buffer.advance(std::mem::size_of::<RawHeaderExtension>());
if buffer.len() < extension_length {
return Err(InvalidInput::new());
}
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: U16::new(self.misc),
length: U16::new(length),
};
buf.extend_from_slice(raw.as_bytes());
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_else(InvalidInput::new)? as usize;
if padding_len == 0 || payload.len() < padding_len {
return Err(InvalidInput::new());
}
}
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()
}
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)
}
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
}
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()
}
}
#[derive(Clone)]
pub struct IncomingRtpPacket {
inner: RtpPacket,
received_at: Instant,
}
impl IncomingRtpPacket {
#[inline]
pub const fn new(packet: RtpPacket, received_at: Instant) -> Self {
Self {
inner: packet,
received_at,
}
}
#[inline]
pub fn received_at(&self) -> Instant {
self.received_at
}
}
impl AsRef<RtpPacket> for IncomingRtpPacket {
#[inline]
fn as_ref(&self) -> &RtpPacket {
&self.inner
}
}
impl Borrow<RtpPacket> for IncomingRtpPacket {
#[inline]
fn borrow(&self) -> &RtpPacket {
&self.inner
}
}
impl Deref for IncomingRtpPacket {
type Target = RtpPacket;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl From<IncomingRtpPacket> for RtpPacket {
#[inline]
fn from(packet: IncomingRtpPacket) -> Self {
packet.inner
}
}
#[derive(Clone)]
pub struct OrderedRtpPacket {
inner: IncomingRtpPacket,
index: u64,
}
impl OrderedRtpPacket {
#[inline]
pub const fn new(inner: IncomingRtpPacket, index: u64) -> Self {
Self { inner, index }
}
#[inline]
pub fn index(&self) -> u64 {
self.index
}
}
impl AsRef<RtpPacket> for OrderedRtpPacket {
#[inline]
fn as_ref(&self) -> &RtpPacket {
&self.inner
}
}
impl AsRef<IncomingRtpPacket> for OrderedRtpPacket {
#[inline]
fn as_ref(&self) -> &IncomingRtpPacket {
&self.inner
}
}
impl Borrow<RtpPacket> for OrderedRtpPacket {
#[inline]
fn borrow(&self) -> &RtpPacket {
&self.inner
}
}
impl Borrow<IncomingRtpPacket> for OrderedRtpPacket {
#[inline]
fn borrow(&self) -> &IncomingRtpPacket {
&self.inner
}
}
impl Deref for OrderedRtpPacket {
type Target = IncomingRtpPacket;
#[inline]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl From<OrderedRtpPacket> for RtpPacket {
#[inline]
fn from(packet: OrderedRtpPacket) -> Self {
packet.inner.into()
}
}
impl From<OrderedRtpPacket> for IncomingRtpPacket {
#[inline]
fn from(packet: OrderedRtpPacket) -> Self {
packet.inner
}
}