use std::io::Seek;
use bit_cursor::{
bit_cursor::BitCursor, bit_read_exts::BitReadExts, byte_order::NetworkOrder, nsw_types::*,
};
pub struct RtpHeader;
impl RtpHeader {
pub fn version(buf: &[u8]) -> u2 {
u2::new((buf[0] & 0b11000000) >> 6)
}
pub fn has_padding(buf: &[u8]) -> bool {
(buf[0] & 0b00100000) != 0
}
pub fn has_extensions(buf: &[u8]) -> bool {
(buf[0] & 0b00010000) != 0
}
pub fn csrc_count(buf: &[u8]) -> u4 {
u4::new(buf[0] & 0b00001111)
}
pub fn marked(buf: &[u8]) -> bool {
(buf[1] & 0b10000000) != 0
}
pub fn payload_type(buf: &[u8]) -> u7 {
u7::new(buf[1] & 0b01111111)
}
pub fn seq_num(buf: &[u8]) -> u16 {
u16::from_be_bytes(buf[3..4].try_into().unwrap())
}
pub fn timestamp(buf: &[u8]) -> u32 {
u32::from_be_bytes(buf[4..8].try_into().unwrap())
}
pub fn ssrc(buf: &[u8]) -> u32 {
u32::from_be_bytes(buf[8..12].try_into().unwrap())
}
pub fn extensions_start_offset(buf: &[u8]) -> usize {
let csrc_count: usize = RtpHeader::csrc_count(buf).into();
12 + csrc_count * 4
}
pub fn payload_offset(buf: &[u8]) -> usize {
RtpHeader::extensions_start_offset(buf)
+ RtpHeader::header_extensions_length_bytes(buf) as usize
}
pub fn header_extensions_length_bytes(buf: &[u8]) -> u16 {
if RtpHeader::has_extensions(buf) {
let mut cursor = BitCursor::new(buf);
let ext_offset = RtpHeader::extensions_start_offset(buf);
cursor
.seek(std::io::SeekFrom::Start((ext_offset as u64 + 2) * 8))
.unwrap();
let length_field = cursor.read_u16::<NetworkOrder>().unwrap();
4 + length_field * 4
} else {
0
}
}
}