mod descriptors;
mod eit;
mod error;
mod nit;
mod pat;
mod pmt;
mod sdt;
mod tdt;
mod tot;
pub use descriptors::*;
pub use eit::*;
pub use error::*;
pub use nit::*;
pub use pat::*;
pub use pmt::*;
pub use sdt::*;
pub use tdt::*;
pub use tot::*;
use crate::ts::{
NULL_PACKET,
PACKET_SIZE,
TsPacketMut,
TsPacketRef,
};
pub struct Sections {
buffer: Vec<u8>,
starts: Vec<usize>,
}
impl Sections {
pub(super) fn new(buffer: Vec<u8>, starts: Vec<usize>) -> Self {
Self { buffer, starts }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.starts.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.starts.len()
}
}
impl core::ops::Index<usize> for Sections {
type Output = [u8];
#[inline]
fn index(&self, index: usize) -> &Self::Output {
let start = self.starts[index];
let end = if index + 1 < self.starts.len() {
self.starts[index + 1]
} else {
self.buffer.len()
};
&self.buffer[start .. end]
}
}
#[derive(Debug, Clone)]
pub struct Psi {
data: [u8; 4096 + 184],
data_length: usize,
head: [u8; 184],
head_length: usize,
section_length: usize,
assembling: bool,
cc: u8,
}
impl Default for Psi {
fn default() -> Psi {
Psi {
data: [0; 4096 + 184],
data_length: 0,
head: [0; 184],
head_length: 0,
section_length: 0,
assembling: false,
cc: 0,
}
}
}
impl Psi {
pub fn new(table_id: u8) -> Self {
let mut psi = Psi::default();
psi.data[0] = table_id;
psi.data[1] = 0xb0;
psi.data[2] = 0x00;
psi
}
pub fn clear(&mut self) {
self.data_length = 0;
self.head_length = 0;
self.section_length = 0;
self.assembling = false;
}
fn append_data(&mut self, cc: u8, payload: &[u8]) -> bool {
if !self.assembling {
return false;
}
if cc != (self.cc + 1) & 0x0f {
self.clear();
return false;
}
if self.head_length > 0 {
self.data[.. self.head_length].copy_from_slice(&self.head[.. self.head_length]);
self.data_length = self.head_length;
self.section_length = 0;
self.head_length = 0;
} else if self.data_length + payload.len() > self.data.len() {
self.clear();
return false;
}
let end = self.data_length + payload.len();
self.data[self.data_length .. end].copy_from_slice(payload);
self.data_length = end;
if self.section_length == 0 && self.data_length >= 3 {
self.section_length = psi_section_length(&self.data);
}
self.section_length != 0
}
pub fn payload(&self) -> Option<&[u8]> {
(self.section_length != 0 && self.data_length >= self.section_length)
.then(|| &self.data[.. self.section_length])
}
pub fn assemble(&mut self, packet: &TsPacketRef) -> Option<&'_ [u8]> {
let payload = packet.payload()?;
let cc = packet.cc();
if packet.is_payload_start() {
let pointer_field = payload[0] as usize;
let payload = &payload[1 ..];
if pointer_field >= payload.len() {
self.clear();
return None;
}
if pointer_field > 0
&& self.append_data(cc, &payload[.. pointer_field])
&& self.data_length >= self.section_length
{
let tail = &payload[pointer_field ..];
self.head_length = tail.len();
self.head[.. self.head_length].copy_from_slice(tail);
self.assembling = true;
self.cc = cc;
return Some(&self.data[.. self.section_length]);
}
let payload = &payload[pointer_field ..];
let end = if payload.len() >= 3 {
self.section_length = psi_section_length(payload);
payload.len().min(self.section_length)
} else {
self.section_length = 0;
payload.len()
};
self.data[.. end].copy_from_slice(&payload[.. end]);
self.data_length = end;
if self.section_length != 0 && self.data_length >= self.section_length {
self.assembling = false;
return Some(&self.data[.. self.section_length]);
}
self.assembling = true;
self.cc = cc;
} else if self.append_data(cc, payload) {
if self.data_length >= self.section_length {
self.assembling = false;
return Some(&self.data[.. self.section_length]);
}
self.cc = cc;
}
None
}
}
#[inline]
pub(super) fn psi_section_length(data: &[u8]) -> usize {
3 + ((u16::from_be_bytes([data[1], data[2]]) & 0x0fff) as usize)
}
pub struct PsiPacketizer {
sections: Sections,
pid: u16,
cc: u8,
section_index: usize,
offset: usize,
}
impl PsiPacketizer {
pub fn new(pid: u16) -> Self {
Self {
sections: Sections {
buffer: Vec::new(),
starts: Vec::new(),
},
pid,
cc: 0,
section_index: 0,
offset: 0,
}
}
pub fn set_sections(&mut self, sections: Sections) {
self.sections = sections;
self.section_index = 0;
self.offset = 0;
}
pub fn reset(&mut self) {
self.section_index = 0;
self.offset = 0;
}
#[inline]
pub fn is_empty(&self) -> bool {
self.section_index >= self.sections.len()
}
pub fn next(&mut self, packet: &mut [u8; PACKET_SIZE]) -> bool {
if self.section_index >= self.sections.len() {
return false;
}
let section = &self.sections[self.section_index];
let mut packet = TsPacketMut::from(packet);
packet.init(self.pid, self.cc);
packet.set_payload();
self.cc = (self.cc + 1) & 0x0F;
let payload = if self.offset == 0 {
packet.set_pusi();
let payload = packet.payload_mut().unwrap();
payload[0] = 0x00;
&mut payload[1 ..]
} else {
packet.payload_mut().unwrap()
};
let available = payload.len();
let remaining = section.len() - self.offset;
let to_copy = available.min(remaining);
payload[.. to_copy].copy_from_slice(§ion[self.offset .. self.offset + to_copy]);
self.offset += to_copy;
if available > to_copy {
let stuffing = &NULL_PACKET.as_ref()[4 ..];
payload[to_copy .. available].copy_from_slice(&stuffing[to_copy .. available]);
}
if self.offset >= section.len() {
self.section_index += 1;
self.offset = 0;
}
true
}
}