Files
filmcraft/crates/mpegts

filmcraft-mpegts

Clean-room MPEG-2 Systems demuxer: transport streams and program streams. Layer L0: depends only on thiserror. Builds for wasm32-unknown-unknown; no unsafe. No GPL/LGPL code (FFmpeg, libavformat) was consulted; FFmpeg is used only as an external fixture generator and test oracle.

Specifications

Document Edition Used for
ITU-T H.222.0 | ISO/IEC 13818-1 2000 (second edition) TS packets, adaptation fields, PCR, PSI (PAT / PMT, CRC-32 of Annex A), PES headers, PTS/DTS, program streams (pack, system header, program stream map), stream types
ISO/IEC 11172-1 1993 MPEG-1 system streams (pack header, PES header stuffing / STD buffer / timestamps)
Blu-ray / AVCHD BDAV MPEG-2 TS layout (192-byte source packets with a 4-byte TP_extra_header; registration HDMV; stream types 0x80-0x92) public descriptions .m2ts / .mts
DVD-Video private stream 1 sub-stream layout (AC-3 / DTS 0x80-0x8F with a 3-byte header, LPCM 0xA0-0xAF with a 6-byte header, sub-pictures 0x20-0x3F) public descriptions .vob
ETSI EN 300 468 (descriptors 0x56, 0x59, 0x6A, 0x7A, 0x7B), ATSC A/52 Annex A (AC-3 in TS) — identifying private PES streams
ISO/IEC 11172-3, 13818-3 (frame headers), ISO/IEC 13818-7 (ADTS), 14496-3 (LOAS), ATSC A/52 (syncinfo, E-AC-3 frmsiz) — audio frame lengths for splitting

What it does

let file = filmcraft_mpegts::open(&bytes)?;           // any ByteSource (file, memory)
for (i, s) in file.streams.iter().enumerate() {
    println!("{:?} {} {} units", s.id, s.codec.name(), s.units.len());
}
let v = file.find(Kind::Video, |_| true).unwrap();
let au: Vec<u8> = file.read_unit(&bytes, v, 0)?;      // the first access unit
  • Transport streams: 188-byte packets, 192-byte BDAV packets (sync byte after a 4-byte arrival timestamp) and 204-byte packets; the packet size is sniffed from five consecutive sync bytes. Lost sync resynchronises on the next aligned run. PSI sections are reassembled across packets and checked with the MPEG CRC-32; the first program of the PAT is demuxed. Continuity counter errors, CRC errors and resyncs are reported as warnings.
  • Program streams: MPEG-2 and MPEG-1 packs, system headers, the program stream map (stream types for elementary stream ids), padding, private stream 2 (DVD navigation) skipped, private stream 1 split by sub-stream id. Garbage resynchronises on the next pack or PES start code.
  • Streams: MPEG-1/2 video, H.264, HEVC, MPEG audio, AAC (ADTS, LATM/LOAS), AC-3, E-AC-3, DTS, TrueHD, Blu-ray LPCM, DVD LPCM (format from the sub-stream header), PGS / DVB / teletext subtitles; ISO 639 language from the PMT.
  • Access units, found while the file is scanned (one pass, streaming; only a few bytes of each stream are buffered):
    • MPEG-1/2 video: a coded frame — a frame picture, or two field pictures (paired by picture_structure) — with the sequence / GOP headers before it; picture type, temporal reference, field structure, top_field_first, repeat_first_field, progressive_frame, closed GOP / broken link. A PTS belongs to the unit whose picture start code is in that PES.
    • H.264 / HEVC: PES packets with a timestamp (a PES without one continues the previous unit); random access from IDR / IRAP NAL types; disposable when every slice is a non-reference.
    • Audio: one frame per unit from the frame headers (sync re-hunted after garbage; a header found while hunting is confirmed by the next one); a PTS belongs to the first frame starting in the PES.
    • LPCM and everything else: one PES packet per unit.
  • Timestamps: 33-bit PTS/DTS unwrapped across the wrap (and back, for B pictures shown before a wrap that came earlier); PCR / SCR range.
  • Reading: a unit records only the position of its first packet and its offset in that packet's payload; read_unit re-reads from there (the index costs a few dozen bytes per unit, not per packet).

Tests

  • src/tests.rs: a small TS muxer (PAT, PMT with CRC, PES split into 188- or 192-byte packets with adaptation-field stuffing) and PS writer (packs ≤ 2000 bytes, so frames span PES packets; AC-3 in private stream 1): every access unit reads back byte-identical with its PTS, key and disposable flags, field pairs as one unit, audio frames with the first-in-PES timestamp; 33-bit unwrap; truncation every 37 bytes and 400 random mutations never panic.
  • src/es.rs, src/pes.rs: frame sizes (MPEG audio layers I-III, MPEG-2 LSF, AC-3 at all rates), MPEG-2 and MPEG-1 PES headers.
  • crates/codecs/tests/mpeg_oracle.rs: FFmpeg-written TS / M2TS / VOB / MPEG-1 system files — frame counts and every frame's PTS equal ffprobe's, decoded media against FFmpeg (see filmcraft-codecs).

Gaps

  • One program per TS (the first in the PAT); no program switching, no section-based metadata (SDT / EIT), no scrambled streams.
  • H.264 / HEVC access units follow PES packets: streams that put several pictures in one PES packet (rare in practice; not seen in broadcast, AVCHD or FFmpeg output) would be indexed as one unit.
  • DVD navigation (IFO / NAV packets), multiple VOB concatenation and angle interleaving are not handled; each file opens on its own.