use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccessUnit {
pub pid: u16,
pub pts: Option<u64>,
pub dts: Option<u64>,
pub data: Vec<u8>,
}
pub fn reconstruct_access_units(ts: &[u8], pids: &[u16]) -> Vec<AccessUnit> {
const TS_PACKET_SIZE: usize = 188;
assert_eq!(
ts.len() % TS_PACKET_SIZE,
0,
"ts buffer length {} is not a multiple of 188",
ts.len()
);
let pid_set = {
let mut set = alloc::collections::BTreeSet::new();
for &pid in pids {
set.insert(pid);
}
set
};
let mut assemblers: alloc::collections::BTreeMap<u16, mpeg_pes::PesAssembler> =
alloc::collections::BTreeMap::new();
let mut result: Vec<AccessUnit> = Vec::new();
for chunk in ts.chunks(TS_PACKET_SIZE) {
let raw: [u8; TS_PACKET_SIZE] = match chunk.try_into() {
Ok(a) => a,
Err(_) => continue, };
let pkt = match mpeg_ts::OwnedTsPacket::parse(raw) {
Ok(p) => p,
Err(_) => continue,
};
if !pid_set.contains(&pkt.pid) {
continue;
}
let payload = match pkt.payload() {
Some(p) => p,
None => continue,
};
let asm = assemblers.entry(pkt.pid).or_default();
if let Some(completed) = asm.feed(pkt.pusi, payload) {
let au = parse_au(pkt.pid, completed);
result.push(au);
}
}
for (&pid, asm) in assemblers.iter_mut() {
if let Some(completed) = asm.flush() {
let au = parse_au(pid, completed);
result.push(au);
}
}
result
}
fn parse_au(pid: u16, data: Vec<u8>) -> AccessUnit {
let (pts, dts) = match mpeg_pes::PesPacket::parse(&data) {
Ok(pkt) => {
let pts = pkt.header.as_ref().and_then(|h| h.pts).map(|p| p.ticks());
let dts = pkt.header.as_ref().and_then(|h| h.dts).map(|d| d.ticks());
(pts, dts)
}
Err(_) => (None, None),
};
AccessUnit {
pid,
pts,
dts,
data,
}
}