pub mod adaptation_field;
pub mod header;
pub mod payload;
use adaptation_field::AdaptationField;
use adaptation_field::StuffingAdaptationField;
#[cfg(feature = "tracing")]
use tracing::trace;
use crate::ErrorKind;
use crate::packet::adaptation_field::DataAdaptationField;
use crate::packet::header::TsHeader;
use crate::packet::payload::TsPayload;
pub(crate) const PACKET_SIZE: usize = 188;
pub const HEADER_SIZE: u8 = 4;
pub struct TsPacket {
header: TsHeader,
adaptation_field: Option<AdaptationField>,
payload: Option<TsPayload>,
}
impl TsPacket {
pub fn from_bytes(buf: &mut [u8]) -> Result<TsPacket, ErrorKind> {
let buffer_length = buf.len();
let header_bytes = Box::from(buf[0..HEADER_SIZE as usize].to_vec());
#[cfg(feature = "tracing")]
trace!("Parsing TSPacket from raw bytes: {:02X?}", buf);
let header = TsHeader::from_bytes(&header_bytes)?;
let mut read_idx: usize = HEADER_SIZE as usize;
let adaptation_field = if header.has_adaptation_field() {
#[cfg(feature = "tracing")]
trace!("Adaptation field exists for TSPacket");
let length = buf[read_idx];
if length != 0 {
let af = DataAdaptationField::from_bytes(
&mut buf[read_idx..buffer_length],
);
read_idx += af.adaptation_field_length() as usize + 1;
Some(AdaptationField::Data(af))
} else {
let af = StuffingAdaptationField::new();
read_idx += af.adaptation_field_length() as usize;
Some(AdaptationField::Stuffing(af))
}
} else {
None
};
let payload = if header.has_payload() {
#[cfg(feature = "tracing")]
trace!("Payload exists for TSPacket");
let payload_bytes = &buf[read_idx..buf.len()];
let remainder = (PACKET_SIZE - read_idx) as u8;
if header.pusi() && payload_bytes[0] > remainder {
return Err(ErrorKind::InvalidPayloadPointer {
pointer: payload_bytes[0],
remainder,
});
}
Some(TsPayload::from_bytes(
header.pusi(),
header.continuity_counter(),
payload_bytes,
))
} else {
None
};
let packet = TsPacket { header, adaptation_field, payload };
Ok(packet)
}
pub fn header(&self) -> TsHeader {
self.header
}
pub fn has_adaptation_field(&self) -> bool {
self.header.has_adaptation_field()
}
pub fn has_payload(&self) -> bool {
self.header.has_payload()
}
pub fn adaptation_field(&self) -> Option<AdaptationField> {
self.adaptation_field.clone()
}
pub fn payload(&self) -> &Option<TsPayload> {
&self.payload
}
pub fn to_payload(self) -> Option<TsPayload> {
self.payload
}
}
#[cfg(test)]
mod tests {
use test_case::test_case;
use super::*;
use crate::AdaptationFieldControl;
fn packet_1() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
let packet = [
0x47, 0x41, 0x02, 0x10, 0x00, 0x00, 0x01, 0xFC, 0x01, 0x10, 0x84, 0x80, 0x05, 0x21, 0x02, 0x95,
0x32, 0x6F, 0x00, 0x00, 0xDF, 0x01, 0x03, 0x06, 0x0E, 0x2B, 0x34,
0x02, 0x0B, 0x01, 0x01, 0x0E, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00,
0x00, 0x81, 0xF1, 0x02, 0x08, 0x00, 0x04, 0xCA, 0x14, 0x28, 0x06,
0x0E, 0xEA, 0x03, 0x15, 0x45, 0x53, 0x52, 0x49, 0x5F, 0x4D, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x43, 0x6F, 0x6C, 0x6C,
0x65, 0x63, 0x74, 0x04, 0x06, 0x4E, 0x39, 0x37, 0x38, 0x32, 0x36,
0x05, 0x02, 0x70, 0x12, 0x06, 0x02, 0x15, 0xB3, 0x07, 0x02, 0xEF,
0x62, 0x0A, 0x05, 0x43, 0x32, 0x30, 0x38, 0x42, 0x0B, 0x00, 0x0C,
0x00, 0x0D, 0x04, 0x3A, 0x72, 0x80, 0x98, 0x0E, 0x04, 0xB5, 0x6C,
0xF5, 0xB9, 0x0F, 0x02, 0x31, 0x4F, 0x10, 0x02, 0x04, 0x5C, 0x11,
0x02, 0x02, 0x73, 0x12, 0x04, 0xB4, 0xCC, 0xCC, 0xCE, 0x13, 0x04,
0xF1, 0x81, 0x6C, 0x17, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, 0x15,
0x04, 0x00, 0x1E, 0x0A, 0x4F, 0x16, 0x02, 0x00, 0x00, 0x17, 0x04,
0x3A, 0x76, 0x87, 0xAF, 0x18, 0x04, 0xB5, 0x70, 0x74, 0xF2, 0x19,
0x02, 0x23, 0x99, 0x1A, 0x02, 0x01, 0x7B, 0x1B, 0x02, 0x00, 0x75,
0x1C, 0x02, 0xFF, 0xF1, 0x1D, 0x02, 0x02, ];
(
Box::new(packet),
crate::AdaptationFieldControl::Payload,
Box::new([0x00, 0x01, 0xFC, 0x01]),
)
}
fn packet_2() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>) {
let packet = [
0x47, 0x01, 0x02, 0x31, 0x59, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x03, 0x1E, 0x02, 0xFE, 0x9B, 0x1F, 0x02, 0xFF, 0x93, 0x20, 0x02,
0x00, 0x0F, 0x21, 0x02, 0xFE, 0x1B, 0x2F, 0x01, 0x00, 0x30, 0x2A,
0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x04, 0x2F, 0x2F, 0x43,
0x41, 0x04, 0x00, 0x05, 0x00, 0x06, 0x02, 0x43, 0x41, 0x15, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x05, 0x38, 0x01,
0x00, 0x3B, 0x08, 0x46, 0x69, 0x72, 0x65, 0x62, 0x69, 0x72, 0x64,
0x41, 0x01, 0x01, 0x48, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x02, 0xF9, 0x05, ];
(
Box::new(packet),
crate::AdaptationFieldControl::AdaptationAndPayload,
Box::new([0x03, 0x1E, 0x02, 0xFE]),
)
}
#[test_case(packet_2)]
#[test_case(packet_1)]
fn from_bytes(
packet: fn() -> (Box<[u8]>, AdaptationFieldControl, Box<[u8]>),
) {
let (mut buf, adaptation_field_control, first_packet_bytes) = packet();
let packet = TsPacket::from_bytes(&mut buf).unwrap();
assert_eq!(
packet.header().adaptation_field_control(),
adaptation_field_control,
"Transport Error Indicator is incorrect"
);
match packet.payload().clone().unwrap().get_payload_data() {
payload::TsPayloadData::StartData(start, _end) => assert!(
start.iter().eq(first_packet_bytes.iter()),
"First payload bytes are incorrect: {:02X?}",
start
),
_ => panic!(),
};
}
}