use crate::pes;
use log::warn;
use std::convert::TryFrom;
use std::fmt;
#[derive(Eq, PartialEq, Debug)]
pub enum AdaptationControl {
Reserved,
PayloadOnly,
AdaptationFieldOnly,
AdaptationFieldAndPayload,
}
impl AdaptationControl {
#[inline(always)]
fn from(val: u8) -> AdaptationControl {
match val {
0 => AdaptationControl::Reserved,
1 => AdaptationControl::PayloadOnly,
2 => AdaptationControl::AdaptationFieldOnly,
3 => AdaptationControl::AdaptationFieldAndPayload,
_ => panic!("invalid value {}", val),
}
}
#[inline(always)]
pub fn has_payload(self) -> bool {
match self {
AdaptationControl::Reserved | AdaptationControl::AdaptationFieldOnly => false,
AdaptationControl::PayloadOnly | AdaptationControl::AdaptationFieldAndPayload => true,
}
}
}
#[derive(Eq, PartialEq, Debug)]
pub enum TransportScramblingControl {
NotScrambled,
Undefined(u8),
}
impl TransportScramblingControl {
fn from(val: u8) -> TransportScramblingControl {
match val {
0 => TransportScramblingControl::NotScrambled,
1..=3 => TransportScramblingControl::Undefined(val),
_ => panic!("invalid value {}", val),
}
}
}
#[derive(Copy, Clone)]
pub struct ClockRef {
base: u64,
extension: u16,
}
impl PartialEq for ClockRef {
fn eq(&self, other: &ClockRef) -> bool {
self.base == other.base && self.extension == other.extension
}
}
impl From<ClockRef> for u64 {
fn from(pcr: ClockRef) -> u64 {
pcr.base * 300 + u64::from(pcr.extension)
}
}
impl fmt::Debug for ClockRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "PCR{{{:08x}:{:04x}}}", self.base, self.extension)
}
}
impl ClockRef {
pub fn from_slice(data: &[u8]) -> ClockRef {
ClockRef {
base: u64::from(data[0]) << 25
| u64::from(data[1]) << 17
| u64::from(data[2]) << 9
| u64::from(data[3]) << 1
| u64::from(data[4]) >> 7,
extension: (u16::from(data[4]) & 0b1) << 8 | u16::from(data[5]),
}
}
pub fn from_parts(base: u64, extension: u16) -> ClockRef {
assert!(base < (1 << 33));
assert!(extension < (1 << 9));
ClockRef { base, extension }
}
pub fn base(&self) -> u64 {
self.base
}
pub fn extension(&self) -> u16 {
self.extension
}
}
#[derive(Debug, PartialEq)]
pub enum AdaptationFieldError {
FieldNotPresent,
NotEnoughData,
SpliceTimestampError(pes::TimestampError),
}
pub struct AdaptationField<'buf> {
buf: &'buf [u8],
}
impl<'buf> AdaptationField<'buf> {
pub fn new(buf: &'buf [u8]) -> AdaptationField<'buf> {
assert!(!buf.is_empty());
AdaptationField { buf }
}
pub fn discontinuity_indicator(&self) -> bool {
self.buf[0] & 0b1000_0000 != 0
}
pub fn random_access_indicator(&self) -> bool {
self.buf[0] & 0b0100_0000 != 0
}
pub fn elementary_stream_priority_indicator(&self) -> u8 {
(self.buf[0] & 0b10_0000) >> 5
}
fn pcr_flag(&self) -> bool {
self.buf[0] & 0b1_0000 != 0
}
fn opcr_flag(&self) -> bool {
self.buf[0] & 0b1000 != 0
}
fn splicing_point_flag(&self) -> bool {
self.buf[0] & 0b100 != 0
}
fn transport_private_data_flag(&self) -> bool {
self.buf[0] & 0b10 != 0
}
fn adaptation_field_extension_flag(&self) -> bool {
self.buf[0] & 0b1 != 0
}
fn slice(&self, from: usize, to: usize) -> Result<&'buf [u8], AdaptationFieldError> {
if to > self.buf.len() {
Err(AdaptationFieldError::NotEnoughData)
} else {
Ok(&self.buf[from..to])
}
}
const PCR_SIZE: usize = 6;
pub fn pcr(&self) -> Result<ClockRef, AdaptationFieldError> {
if self.pcr_flag() {
Ok(ClockRef::from_slice(self.slice(1, 1 + Self::PCR_SIZE)?))
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn opcr_offset(&self) -> usize {
if self.pcr_flag() {
1 + Self::PCR_SIZE
} else {
1
}
}
pub fn opcr(&self) -> Result<ClockRef, AdaptationFieldError> {
if self.opcr_flag() {
let off = self.opcr_offset();
Ok(ClockRef::from_slice(self.slice(off, off + Self::PCR_SIZE)?))
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn splice_countdown_offset(&self) -> usize {
self.opcr_offset() + if self.opcr_flag() { Self::PCR_SIZE } else { 0 }
}
pub fn splice_countdown(&self) -> Result<u8, AdaptationFieldError> {
if self.splicing_point_flag() {
let off = self.splice_countdown_offset();
Ok(self.slice(off, off + 1)?[0])
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn transport_private_data_offset(&self) -> usize {
self.splice_countdown_offset() + if self.splicing_point_flag() { 1 } else { 0 }
}
pub fn transport_private_data(&self) -> Result<&[u8], AdaptationFieldError> {
if self.transport_private_data_flag() {
let off = self.transport_private_data_offset();
let len = self.slice(off, off + 1)?[0] as usize;
Ok(self.slice(off + 1, off + 1 + len)?)
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn adaptation_field_extension_offset(&self) -> Result<usize, AdaptationFieldError> {
let off = self.transport_private_data_offset();
Ok(off
+ if self.transport_private_data_flag() {
let len = self.slice(off, off + 1)?[0] as usize;
len + 1
} else {
0
})
}
pub fn adaptation_field_extension(
&self,
) -> Result<AdaptationFieldExtension<'buf>, AdaptationFieldError> {
if self.adaptation_field_extension_flag() {
let off = self.adaptation_field_extension_offset()?;
let len = self.slice(off, off + 1)?[0] as usize;
AdaptationFieldExtension::new(self.slice(off + 1, off + 1 + len)?)
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
}
impl<'buf> fmt::Debug for AdaptationField<'buf> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("AdaptationField");
d.field("discontinuity_indicator", &self.discontinuity_indicator());
d.field("random_access_indicator", &self.random_access_indicator());
d.field(
"elementary_stream_priority_indicator",
&self.elementary_stream_priority_indicator(),
);
d.field("pcr", &self.pcr());
d.field("opcr", &self.opcr());
d.field("splice_countdown", &self.splice_countdown());
d.field("transport_private_data", &self.transport_private_data());
d.field(
"adaptation_field_extension",
&self.adaptation_field_extension(),
);
d.finish()
}
}
pub struct AdaptationFieldExtension<'buf> {
buf: &'buf [u8],
}
impl<'buf> AdaptationFieldExtension<'buf> {
pub fn new(buf: &'buf [u8]) -> Result<AdaptationFieldExtension<'buf>, AdaptationFieldError> {
if buf.is_empty() {
Err(AdaptationFieldError::NotEnoughData)
} else {
Ok(AdaptationFieldExtension { buf })
}
}
fn slice(&self, from: usize, to: usize) -> Result<&'buf [u8], AdaptationFieldError> {
if to > self.buf.len() {
Err(AdaptationFieldError::NotEnoughData)
} else {
Ok(&self.buf[from..to])
}
}
fn ltw_flag(&self) -> bool {
self.buf[0] & 0b1000_0000 != 0
}
fn piecewise_rate_flag(&self) -> bool {
self.buf[0] & 0b0100_0000 != 0
}
fn seamless_splice_flag(&self) -> bool {
self.buf[0] & 0b0010_0000 != 0
}
pub fn ltw_offset(&self) -> Result<Option<u16>, AdaptationFieldError> {
if self.ltw_flag() {
let dat = self.slice(1, 3)?;
let ltw_valid_flag = dat[0] & 0b1000_0000 != 0;
Ok(if ltw_valid_flag {
Some(u16::from(dat[0] & 0b0111_1111) << 8 | u16::from(dat[1]))
} else {
None
})
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn piecewise_rate_offset(&self) -> usize {
1 + if self.ltw_flag() { 2 } else { 0 }
}
pub fn piecewise_rate(&self) -> Result<u32, AdaptationFieldError> {
if self.piecewise_rate_flag() {
let off = self.piecewise_rate_offset();
let dat = self.slice(off, off + 3)?;
Ok(u32::from(dat[0] & 0b0011_1111) << 16 | u32::from(dat[1]) << 8 | u32::from(dat[2]))
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
fn seamless_splice_offset(&self) -> usize {
self.piecewise_rate_offset() + if self.piecewise_rate_flag() { 3 } else { 0 }
}
pub fn seamless_splice(&self) -> Result<SeamlessSplice, AdaptationFieldError> {
if self.seamless_splice_flag() {
let off = self.seamless_splice_offset();
let dat = self.slice(off, off + 5)?;
Ok(SeamlessSplice {
splice_type: dat[0] >> 4,
dts_next_au: pes::Timestamp::from_bytes(dat)
.map_err(AdaptationFieldError::SpliceTimestampError)?,
})
} else {
Err(AdaptationFieldError::FieldNotPresent)
}
}
}
impl<'buf> fmt::Debug for AdaptationFieldExtension<'buf> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("AdaptationFieldExtension");
d.field("ltw_offset", &self.ltw_offset());
d.field("piecewise_rate", &self.piecewise_rate());
d.field("seamless_splice", &self.seamless_splice());
d.finish()
}
}
#[derive(Debug, PartialEq)]
pub struct SeamlessSplice {
pub splice_type: u8,
pub dts_next_au: pes::Timestamp,
}
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct ContinuityCounter {
val: u8,
}
impl From<u8> for ContinuityCounter {
#[inline]
fn from(count: u8) -> ContinuityCounter {
ContinuityCounter::new(count)
}
}
impl ContinuityCounter {
#[inline]
pub fn new(count: u8) -> ContinuityCounter {
assert!(count < 0b10000);
ContinuityCounter { val: count }
}
#[inline]
pub fn count(self) -> u8 {
self.val
}
#[inline]
pub fn follows(self, other: ContinuityCounter) -> bool {
(other.val + 1) & 0b1111 == self.val
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Pid(u16);
impl Pid {
pub const MAX_VALUE: u16 = 0x1fff;
pub const PID_COUNT: usize = (Self::MAX_VALUE + 1) as usize;
#[doc(hidden)]
pub const PAT: Pid = Pid::new(0);
#[doc(hidden)]
pub const STUFFING: Pid = Pid::new(0x1fff);
pub const fn new(pid: u16) -> Pid {
const_assert!(pid <= 0x1fff);
Pid(pid)
}
}
impl TryFrom<u16> for Pid {
type Error = ();
fn try_from(value: u16) -> Result<Self, Self::Error> {
if value <= Pid::MAX_VALUE {
Ok(Pid(value))
} else {
Err(())
}
}
}
impl From<Pid> for u16 {
#[inline]
fn from(pid: Pid) -> Self {
pid.0
}
}
impl From<Pid> for usize {
#[inline]
fn from(pid: Pid) -> Self {
pid.0 as usize
}
}
impl fmt::Debug for Pid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "Pid({:04x})", self.0)
}
}
pub struct Packet<'buf> {
buf: &'buf [u8],
}
const FIXED_HEADER_SIZE: usize = 4;
const ADAPTATION_FIELD_OFFSET: usize = FIXED_HEADER_SIZE + 1;
impl<'buf> Packet<'buf> {
pub const SYNC_BYTE: u8 = 0x47;
pub const SIZE: usize = 188;
#[inline(always)]
pub fn is_sync_byte(b: u8) -> bool {
b == Self::SYNC_BYTE
}
#[inline(always)]
pub fn new(buf: &'buf [u8]) -> Packet<'buf> {
assert_eq!(buf.len(), Self::SIZE);
assert!(Packet::is_sync_byte(buf[0]));
Packet { buf }
}
#[inline(always)]
pub fn try_new(buf: &'buf [u8]) -> Option<Packet<'buf>> {
assert_eq!(buf.len(), Self::SIZE);
if Packet::is_sync_byte(buf[0]) {
Some(Packet { buf })
} else {
None
}
}
#[inline]
pub fn transport_error_indicator(&self) -> bool {
self.buf[1] & 0b1000_0000 != 0
}
#[inline]
pub fn payload_unit_start_indicator(&self) -> bool {
self.buf[1] & 0b0100_0000 != 0
}
pub fn transport_priority(&self) -> bool {
self.buf[1] & 0b0010_0000 != 0
}
#[inline]
pub fn pid(&self) -> Pid {
Pid(u16::from(self.buf[1] & 0b0001_1111) << 8 | u16::from(self.buf[2]))
}
pub fn transport_scrambling_control(&self) -> TransportScramblingControl {
TransportScramblingControl::from(self.buf[3] >> 6 & 0b11)
}
#[inline]
pub fn adaptation_control(&self) -> AdaptationControl {
AdaptationControl::from(self.buf[3] >> 4 & 0b11)
}
#[inline]
pub fn continuity_counter(&self) -> ContinuityCounter {
ContinuityCounter::new(self.buf[3] & 0b0000_1111)
}
fn adaptation_field_length(&self) -> usize {
self.buf[4] as usize
}
pub fn adaptation_field(&self) -> Option<AdaptationField<'buf>> {
match self.adaptation_control() {
AdaptationControl::Reserved | AdaptationControl::PayloadOnly => None,
AdaptationControl::AdaptationFieldOnly => {
let len = self.adaptation_field_length();
if len != (Self::SIZE - ADAPTATION_FIELD_OFFSET) {
warn!(
"invalid adaptation_field_length for AdaptationFieldOnly: {}",
len
);
return None;
}
Some(self.mk_af(len))
}
AdaptationControl::AdaptationFieldAndPayload => {
let len = self.adaptation_field_length();
if len > 182 {
warn!(
"invalid adaptation_field_length for AdaptationFieldAndPayload: {}",
len
);
return None;
}
if len == 0 {
return None;
}
Some(self.mk_af(len))
}
}
}
fn mk_af(&self, len: usize) -> AdaptationField<'buf> {
AdaptationField::new(&self.buf[ADAPTATION_FIELD_OFFSET..ADAPTATION_FIELD_OFFSET + len])
}
#[inline(always)]
pub fn payload(&self) -> Option<&'buf [u8]> {
match self.adaptation_control() {
AdaptationControl::Reserved | AdaptationControl::AdaptationFieldOnly => None,
AdaptationControl::PayloadOnly | AdaptationControl::AdaptationFieldAndPayload => {
self.mk_payload()
}
}
}
#[inline]
fn mk_payload(&self) -> Option<&'buf [u8]> {
let offset = self.content_offset();
if offset == self.buf.len() {
warn!("no payload data present");
None
} else if offset > self.buf.len() {
warn!(
"adaptation_field_length {} too large",
self.adaptation_field_length()
);
None
} else {
Some(&self.buf[offset..])
}
}
pub fn buffer(&self) -> &'buf [u8] {
self.buf
}
#[inline]
fn content_offset(&self) -> usize {
match self.adaptation_control() {
AdaptationControl::Reserved | AdaptationControl::PayloadOnly => FIXED_HEADER_SIZE,
AdaptationControl::AdaptationFieldOnly
| AdaptationControl::AdaptationFieldAndPayload => {
ADAPTATION_FIELD_OFFSET + self.adaptation_field_length()
}
}
}
}
#[cfg(test)]
mod test {
use crate::packet::*;
use crate::pes;
#[test]
fn pid() {
assert!(Pid::try_from(0x2000).is_err());
}
#[test]
#[should_panic]
fn zero_len() {
let buf = [0u8; 0];
Packet::new(&buf[..]);
}
#[test]
fn test_xmas_tree() {
let mut buf = [0xffu8; Packet::SIZE];
buf[0] = Packet::SYNC_BYTE;
buf[4] = 28;
buf[19] = 1;
buf[21] = 11;
let pk = Packet::new(&buf[..]);
assert_eq!(u16::from(pk.pid()), 0b1111111111111u16);
assert!(pk.transport_error_indicator());
assert!(pk.payload_unit_start_indicator());
assert!(pk.transport_priority());
assert_eq!(
pk.transport_scrambling_control(),
TransportScramblingControl::Undefined(3)
);
assert_eq!(
pk.adaptation_control(),
AdaptationControl::AdaptationFieldAndPayload
);
assert_eq!(pk.continuity_counter().count(), 0b1111);
assert!(pk.adaptation_field().is_some());
let ad = pk.adaptation_field().unwrap();
assert!(ad.discontinuity_indicator());
assert_eq!(
ad.pcr(),
Ok(ClockRef::from_parts(
0b1_1111_1111_1111_1111_1111_1111_1111_1111,
0b1_1111_1111
))
);
assert_eq!(1234 * 300 + 56, u64::from(ClockRef::from_parts(1234, 56)));
assert_eq!(
ad.opcr(),
Ok(ClockRef::from_parts(
0b1_1111_1111_1111_1111_1111_1111_1111_1111,
0b1_1111_1111
))
);
assert_eq!(ad.splice_countdown(), Ok(0b11111111));
let expected_data = [0xff];
assert_eq!(ad.transport_private_data(), Ok(&expected_data[..]));
let ext = ad.adaptation_field_extension().unwrap();
assert_eq!(ext.ltw_offset(), Ok(Some(0b0111_1111_1111_1111)));
assert_eq!(ext.piecewise_rate(), Ok(0b0011_1111_1111_1111_1111_1111));
assert_eq!(
ext.seamless_splice(),
Ok(SeamlessSplice {
splice_type: 0b1111,
dts_next_au: pes::Timestamp::from_u64(0b1_1111_1111_1111_1111_1111_1111_1111_1111)
})
);
assert!(!format!("{:?}", pk.adaptation_field()).is_empty())
}
#[test]
fn empty_adaptation_field() {
let mut buf = [0xffu8; Packet::SIZE];
buf[0] = Packet::SYNC_BYTE;
buf[4] = 0;
let pk = Packet::new(&buf[..]);
assert_eq!(
pk.adaptation_control(),
AdaptationControl::AdaptationFieldAndPayload
);
assert!(pk.adaptation_field().is_none());
}
#[test]
fn empty_adaptation_field_extension() {
assert!(AdaptationFieldExtension::new(b"").is_err());
}
}