mpeg-ts
MPEG-2 Transport Stream framing for Rust.
Parses and serializes the ITU-T H.222.0 / ISO/IEC 13818-1 TS packet layer:
188-byte TS packets, adaptation fields, PCR, PSI section reassembly, section
packetization, and sync recovery. no_std + alloc — runs on embedded targets
with a heap.
Extracted from dvb-si at the 8.0.0 breaking boundary and published
independently so projects that only need raw TS framing do not have to pull in
the full SI/descriptor stack.
Features
| Feature | Default | Description |
|---|---|---|
std |
yes | Enable std::error::Error impls; disable for embedded |
serde |
yes | Serialize for packet/section types (serialize-only) |
Installation
[]
= "0.1"
For embedded (no_std + alloc):
[]
= { = "0.1", = false }
Quickstart — feed TS packets into a SectionReassembler
use ;
let mut reasm = default;
// Feed 188-byte aligned TS packets; poll for completed PSI sections.
for raw_packet in ts_source
Typed packet inspection
The [ScramblingControl] and [AdaptationFieldControl] enums give typed
access to the 2-bit transport_scrambling_control and adaptation_field_control
fields. Use scrambling_control() / adaptation_field_control() on either
[TsHeader] or [OwnedTsPacket]:
use ;
use OwnedTsPacket;
// On a borrowed TsPacket:
let pkt = parse?;
let sc = pkt.header.scrambling_control;
let afc = pkt.header.adaptation_field_control;
// On an owned OwnedTsPacket:
let owned = parse?;
let sc2 = owned.scrambling_control;
let afc2 = owned.adaptation_field_control;
match sc
# Ok::
Bulk-walking a TS byte stream
The free helper [iter_packets] walks a buffer of concatenated 188-byte packets
without explicit length checks:
use iter_packets;
// Build a buffer of 3 minimal payload-only packets with sync 0x47.
let mut buf = vec!;
for chunk in buf.chunks_exact_mut
for pkt in iter_packets
See examples/iter_packets.rs for a full CLI example
that tallies scrambled vs clear packets across a .ts file.
Building & editing packets
The [OwnedTsPacket] helpers let you construct, mutate, and round-trip TS
packets without manual byte manipulation:
use ;
use OwnedTsPacket;
// Build a null packet (PID 0x1FFF) with a given continuity counter.
let null_raw = null_packet;
let pkt = parse?;
assert_eq!;
assert_eq!;
// Overwrite a continuity counter in-place.
let mut raw = serialize_with_payload;
set_continuity_counter;
let pkt = parse?;
assert_eq!;
// Shift a PCR bearing packet (requires adaptation field with PCR flag).
let mut raw = ;
raw = 0x20; // adaptation-only
raw = 7; // adaptation_field_length
raw = 0x10; // PCR flag
set_pcr?;
let pkt = parse?;
assert_eq!;
# Ok::
Run the worked example:
See examples/edit_packet.rs for a complete walk-through
that builds a PCR-bearing packet, mutates PCR and CC, builds a null
packet, and round-trips a packet header.
Spec
- ITU-T H.222.0 (= ISO/IEC 13818-1): §2.4.3.2 (TS packet), §2.4.4 (PSI section), §2.4.3.3 (adaptation field), §2.4.3.4 (PCR). All wire layouts are cited to the clause in the module doc comments.
Lineage
This crate was extracted from dvb-si at the 8.0.0 release boundary (June
2026). Users migrating from dvb-si ≤ 7.x who used the TS framing layer
directly should replace:
Old (dvb_si::…) |
New (mpeg_ts::…) |
|---|---|
ts::TsPacket |
ts::TsPacket |
ts::SectionReassembler |
ts::SectionReassembler |
mux::SiMux / SectionPacketizer |
mux::SiMux / SectionPacketizer |
resync::TsResync |
resync::TsResync |
pid::Pid |
pid::Pid |
License
Licensed under either of MIT or Apache-2.0, at your option.