Skip to content

Latest commit

 

History

1,044 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rust-broadcast

CI License

Spec-grounded DVB protocol parsers and builders in Rust. Feed a transport stream in; get typed, decoded, serde-ready data out. Every wire layout is cited to its ETSI / ISO clause, has a symmetric serializer, and is round-trip tested.

TS (T2-MI PID) ─▶ dvb-t2mi ─▶ BBFrame ─▶ dvb-bbframe ─▶ inner TS ─▶ mpeg-ts ─▶ dvb-si ─▶ typed SI
   T2-MI pump        AnyPayload      Bbheader + up_iter        SiDemux      AnyTableSection + collect

Each crate is independently useful; together they decode a DVB-T2 modulator feed all the way down to a service name string.

Status & MSRV

Versions 5 lockstep core crates (dvb-si, dvb-t2mi, dvb-bbframe, dvb-conformance, dvb-tools) released together from one v<version> tag; broadcast-common was ejected from that lockstep in #862 and, like every other crate below, versions independently — see each crate's own badge for its current version
MSRV 1.95.0 across the workspace (pinned in rust-toolchain.toml)
Edition 2024 across the workspace
no_std Most parser/builder library crates below build #![no_std] + alloc under --no-default-features (suitable for embedded targets with a heap) — see each crate's own docs for its exact story. dvb-tools, dvb-stream, dvb-ci-runtime, multimux, multimux-cli and other tokio/axum-based crates require std and are not embedded-suitable.

To build a no_std crate for an embedded target, build it directly with --no-default-features rather than the whole workspace (feature unification across the workspace can otherwise mask a std-only call — see docs/ for details), e.g.:

$ cargo build -p dvb-si --no-default-features --locked

The crates

DVB Service Information & MPEG-2 transport

Crate Version Docs What it does
broadcast-common crates.io docs.rs Shared Parse/Serialize traits, the mux container-mux traits, and CRC-32/MPEG-2 that everything else builds on.
dvb-si crates.io docs.rs ETSI EN 300 468 Service Information + MPEG-2 PSI: every table_id and descriptor, DSM-CC carousel, Annex A text, a version-gated SiDemux. TS framing lives in mpeg-ts.
dvb-t2mi crates.io docs.rs ETSI TS 102 773 DVB-T2 Modulator Interface (T2-MI): all 12 packet types + a feed-and-iterate pump.
dvb-bbframe crates.io docs.rs DVB-S2 / S2X / T2 BBFRAME headers (MATYPE/UPL/DFL/SYNCD) + user-packet extraction.
dvb-conformance crates.io docs.rs ETSI TR 101 290 stream conformance monitor: Priority-1/2 + SI-repetition indicators on a caller-supplied clock.
mpeg-ts crates.io docs.rs MPEG-2 TS framing (ITU-T H.222.0 / ISO/IEC 13818-1): TS packet, adaptation field, PCR, PSI section reassembly + packetisation, resync. no_std. Independently versioned.
mpeg-pes crates.io docs.rs PES depacketization + PTS/DTS (ISO/IEC 13818-1 §2.4.3): PesPacket, 33-bit Pts/Dts, per-PID PesAssembler. no_std, depends only on broadcast-common. Independently versioned.
mpeg-ps crates.io docs.rs MPEG-1/2 Program Stream (.mpg/.vob) framing (ISO/IEC 13818-1 §2.5): pack header (42-bit SCR), system header, program stream map (PSM), pack walker; PES via mpeg-pes. no_std. Independently versioned.
dvb-stream crates.io docs.rs Async/tokio stream adapters: SectionStream and T2miEventStream over any AsyncRead source (file, TCP, UDP multicast). Independently versioned (tokio MSRV moves faster than the workspace).

Container muxing, adaptive streaming & DPI signalling

Crate Version Docs What it does
broadcast-hls crates.io docs.rs HLS (M3U8) playlist syntax (RFC 8216 / RFC 8216bis): MediaPlaylist/MasterPlaylist parse + serialize, Low-Latency HLS directives, I-frame trick-play, discontinuity signalling, CENC/CBCS #EXT-X-KEY. Extracted from transmux (issue #878) so a consumer that only needs playlist syntax doesn't pull in the whole container-muxing hub. no_std+alloc, depends only on broadcast-common. Independently versioned.
container-probe crates.io docs.rs Media container-format detection over a byte prefix: MPEG-2 TS (a stride x phase lattice across 188/192/204/208, so M2TS and mid-packet captures are found), ISOBMFF (with a fragmented/progressive layout verdict), Matroska/WebM, MPEG-PS, FLV, MXF, WAV, Ogg, ASF, and the ADTS/MP3/AnnexB elementary streams. Every prober always runs and scores its evidence; the highest wins and a near-tie reports Ambiguous rather than silently picking. Scoring is structural, not magic-byte: a lane needs 50% sync coverage and an elementary stream needs a frame-length chain. no_std+alloc, depends only on broadcast-common. Independently versioned.
transmux crates.io docs.rs Any-to-any media container muxing hub (ISO/IEC 14496-12 / 13818-1 / 23009-1, RFC 8216/3550): demux TS/fMP4/PS/WebM/FLV/RTMP into one neutral IR and mux to CMAF/progressive-MP4/TS/HLS/DASH/LL-DASH/LL-HLS/Smooth, plus CENC decrypt, RTP/RTCP, IR transforms (splice/SSAI, trick-play), and a conformance validator. HLS playlist syntax lives in broadcast-hls. no_std+alloc. Independently versioned.
ts-fix crates.io docs.rs MPEG-2 TS stream-conditioning CLI: continuity/PID-filter/PAT-PMT regen/stuffing/PCR-restamp repair. Independently versioned.
media-doctor crates.io docs.rs Container/stream diagnostics: pluggable lint-style checks (sync, PAT/PMT versioning, CC anomalies, PCR, PTS/DTS monotonicity, SCTE-35 splice consistency) + HLS/fMP4/CMAF playlist and structural validation. Independently versioned.
mp4-emsg crates.io docs.rs ISO BMFF / DASH Event Message Box (emsg): parse and build emsg boxes (v0 and v1) for in-band event signalling (DASH-IF, SCTE-35 inband, ID3). no_std. Independently versioned.
timed-metadata crates.io docs.rs Converts DPI/timed-metadata signalling between SCTE-35, HLS EXT-X-DATERANGE (RFC 8216 §4.4.5.1), and DASH emsg (ANSI/SCTE 214-3): lossless round-trips, 33-bit PTS wrap-unroll via a Timeline. no_std. Independently versioned.
scte35-splice crates.io docs.rs ANSI/SCTE 35 splice information (DPI cueing): every command + splice descriptor, the segmentation assignment tables, round-trip builders. no_std. Independently versioned.
scte104 crates.io docs.rs ANSI/SCTE 104 2023 automation→compression DPI signalling: single/multiple operation messages + all ~20 operations (splice/time_signal/insert-descriptor/segmentation/…). no_std. Independently versioned.
dvb-mabr unpublished Unpublished. DVB multicast ABR (ETSI TS 103 769) session configuration XML parser/serializer. no_std+alloc.
ssai-runtime unpublished Unpublished. Sans-IO SCTE-35 SSAI session core: per-session ad-break state, a pluggable ad-decision trait, splice-point conditioning, and per-session HLS Interstitial (EXT-X-DATERANGE CLASS="com.apple.hls.interstitial") playlist rendering. No HTTP client, no VAST/VMAP. no_std+alloc.
playout-runtime unpublished Unpublished. Sans-IO linear channel playout: a schedule model (programme/ad/slate), transition planning across a join (PTS-rebase offset + discontinuity detection), and SCTE-35 splice_insert() emission points built with scte35-splice. No HTTP, no tokio, no transcoding. no_std+alloc.

RTSP / RTP / SRT streaming & the multimux HTTP origin hub

Crate Version Docs What it does
rtsp-runtime crates.io docs.rs Sans-IO RTSP 1.0 (RFC 2326) session engine: driveable client + server state machines, interleaved RTP/RTCP framing, Basic/Digest/Bearer auth (via broadcast-auth); optional tokio (+ TLS) socket adapter. Independently versioned.
rtp-packet crates.io docs.rs RTP fixed header + CSRC list + generic header extension (RFC 3550 §5.1/§5.3.1) — spec-complete parse/serialize. no_std. Independently versioned.
rtcp-packet crates.io docs.rs RTCP control packets: SR/RR/SDES/BYE/APP + compound packet (RFC 3550 §6) — spec-complete parse/serialize. no_std. Independently versioned.
srt-runtime crates.io docs.rs SRT packet codecs + sans-IO HSv5 Caller-Listener/Rendezvous handshake state machines, ARQ, TSBPD delivery scheduling, Live/File congestion control, optional payload encryption and an optional async UDP socket adapter. no_std core. Independently versioned.
broadcast-auth crates.io docs.rs Shared multi-scheme HTTP/RTSP auth: client Credentials/Authenticator (Basic/Digest/Bearer) + server Verifier (challenge+verify, incl. a reverse-proxy forwarded scheme). Independently versioned.
hls-runtime crates.io docs.rs Sans-IO Low-Latency HLS (RFC 8216bis) client + server engines in one crate (blocking reload, part prefetch, rolling-window origin), with an optional tokio+reqwest IO adapter. Independently versioned.
rtmp-runtime crates.io docs.rs Sans-IO RTMP 1.0 ingest/publish session engine: handshake, chunk-stream (de)assembly, AMF0 command routing, server-side state machine, with an optional tokio socket adapter. Independently versioned.
media-plane crates.io docs.rs The ingress/egress spine a live origin is built on: Dialer/Listener → byte stages → IngestSessionTrunk (bounded sample/segment/event/part rings with cursor subscribers), plus three egress shapes (served/push/segment), tiered retention and DVR pinning. Byte layer is no_std + alloc; Trunk needs std. Independently versioned.
multimux crates.io docs.rs Multi-input (RTSP/RTP/TS-UDP/TS-HTTP/SRT/HLS-pull/DASH-pull/Smooth-pull/RTMP/file), multi-output (LL-HLS/DASH/LL-DASH/Smooth/TS-HLS/catch-up + SRT/RTMP/RTSP push) just-in-time repackaging HTTP origin (tokio + axum), with shared output auth and an external scheme plugin registry. Independently versioned.
multimux-cli crates.io CLI — no library API The multimux CLI binary: config-driven multi-route hub, or a single-route quick start. Independently versioned.
webrtc-runtime unpublished Unpublished. Sans-IO WHIP (RFC 9725) + WHEP (draft-ietf-wish-whep) HTTP signalling engine: SDP offer/answer, Trickle ICE, ICE restart, session lifecycle. No IO adapter — the caller drives HTTP. An optional media feature (ICE + DTLS-SRTP transport) is what multimux's whip/whep features build on; the default build is no_std-capable and never touches it.
rist-runtime unpublished Unpublished. RIST Simple Profile (VSF TR-06-1:2020) RTCP message types: Generic NACK (RFC 4585), Range NACK, RTT Echo, and compound packet builders. no_std+alloc.
st2022 unpublished Unpublished. SMPTE ST 2022-6 HBRMT (SDI-over-IP) RTP payload header parser/serializer. no_std.

Broadcast data carriage (captions, subtitles, ancillary, VBI, multicast)

Crate Version Docs What it does
cc-data crates.io docs.rs DVB closed-caption carriage: cc_data() (ETSI TS 101 154 Table B.9) → typed CEA-608/708 triplets + 608/708 split. no_std. Independently versioned.
dvb-subtitle crates.io docs.rs ETSI EN 300 743 DVB (bitmap) subtitling: page/region/CLUT/object/display-definition/disparity segments + 2/4/8-bit pixel-data sub-blocks, fed the PES data field. no_std, depends only on broadcast-common. Independently versioned.
st291 crates.io docs.rs SMPTE ST 291-1 ancillary (ANC) data content: typed parse/serialize for its transports — ST 2038:2021 MPEG-2 TS/PES carriage (anc_data_descriptor + ANC data PES packet) and RFC 8331 / ST 2110-40 RTP carriage. no_std. Independently versioned.
dvb-vbi crates.io docs.rs VBI data carriage in DVB (ETSI EN 301 775) — the PES data field: VPS, WSS, Closed Captioning, EBU/Inverted Teletext, and monochrome 4:2:2 luminance sample data units. no_std. Independently versioned.
caption-convert unpublished Unpublished. CEA-608/708 and EBU Teletext caption conversion to WebVTT, and WebVTT <-> SRT, layered on the extractors timed-metadata already implements. DVB bitmap subtitles and TTML/IMSC source conversion are documented gaps (see crate docs), never silently degraded. no_std+alloc.
ttml-subtitle crates.io docs.rs W3C TTML2 / IMSC 1.1 timed-text subtitle parser: full TTML2 element tree (26 elements, 56 style properties), exhaustive <time-expression> grammar, and IMSC 1.1 profile validation (159-row feature disposition table). Parse/validate split; from-scratch authoring. no_std+alloc. Independently versioned.
ule crates.io docs.rs Unidirectional Lightweight Encapsulation (RFC 4326 + RFC 5163): SNDU framing, extension-header chains, and TS-packet de-fragmentation over DVB-S/T/C MPEG-2 TS. no_std. Independently versioned.
rmt-flute crates.io docs.rs ALC/LCT/FLUTE/NORM multicast object-delivery wire formats (RFC 5651/5775/6726/5740): LCT headers, header-extension chains, ALC + FEC Payload IDs, FLUTE EXT_FDT/EXT_CENC, and NORM messages. no_std. Independently versioned. (Renamed from dvb-flute, which implemented no DVB standard; all dvb-flute versions are yanked.)
st12-1 crates.io docs.rs SMPTE ST 12-1:2014 Linear Timecode (LTC) — the 80-bit logical LTC codeword: BCD time address, drop/color frame flags, binary groups, sync word. no_std. Independently versioned.
st337 crates.io docs.rs SMPTE ST 337-2015 non-PCM audio/data burst-preamble framing over AES3 — spec-complete parse/serialize. no_std. Independently versioned.
rdd29 crates.io docs.rs SMPTE RDD 29:2019 Dolby Atmos bitstream — frame/element framing + bed/object metadata. no_std. Independently versioned.
st377-1 crates.io docs.rs SMPTE ST 377-1:2019 Material Exchange Format (MXF) — KLV framing, Partition/Primer Pack, local-set structural metadata, Random Index Pack. no_std. Independently versioned.

ATSC 3.0 (A/331)

Parsers for the ATSC 3.0 signalling/delivery stack — the ATSC analogue of the DVB SI + multicast-delivery crates above. Both crates are unpublished; see docs/ for maturity notes before depending on either.

Crate Version Docs What it does
atsc3 unpublished Unpublished. ATSC 3.0 (A/331) LLS binary envelope + Service List Table (SLT) parser. no_std+alloc.
atsc3-route unpublished Unpublished. ATSC A/331 Annex A ROUTE binary framing: EXT_ROUTE_PRESENTATION_TIME/EXT_TOL LCT header extensions, source/repair FEC Payload ID layouts, and the Codepoint (CP) delivery-object semantics table. Built on rmt-flute's LCT/ALC/FLUTE; no XML/S-TSID/SLS. no_std+alloc.

Conditional access

Crate Version Docs What it does
dvb-ci crates.io docs.rs DVB Common Interface (ETSI EN 50221): APDU/resource objects (ca_info, ca_pmt, ca_pmt_reply, application_info, …), ASN.1 length codec, SPDU/TPDU framing, and a build_ca_pmt builder from a dvb-si PMT. no_std. Independently versioned.
dvb-ci-runtime crates.io docs.rs Pure-Rust EN 50221 DVB Common Interface driver runtime: device I/O, TPDU/SPDU poll loop, and resource state machines over the dvb-ci codecs. Independently versioned.
dvb-csa crates.io docs.rs DVB Common Scrambling Algorithm (CSA2): pure-Rust, oracle-validated block + stream cipher. Scramble/descramble TS payloads with an 8-byte control word. no_std. Independently versioned.
dvb-simulcrypt crates.io docs.rs DVB SimulCrypt head-end CA message framing (ETSI TS 103 197): the generic TLV message structure plus the ECMG⇔SCS and EMMG/PDG⇔MUX registries. Signalling only — CW/ECM/EMM/datagram payloads stay opaque. no_std. Independently versioned.

Diagnostics & tooling

Crate Version Docs What it does
dvb-tools crates.io CLI — no library API Command-line analyzer over the family: dump / services / epg / pids / t2mi.
broadcast-loudness crates.io docs.rs EBU R 128 / ITU-R BS.1770-5 loudness measurement: K-weighting, integrated/short-term/momentary loudness (LUFS), loudness range (LRA), and true-peak (dBTP). no_std+alloc, depends only on broadcast-common. Independently versioned.
compliance-probe unpublished Unpublished. Live probe over a media-plane Trunk/ByteTap: drives dvb-conformance's TR 101 290 indicators, a PCR-drift/jitter estimate (explicitly distinct from TR 101 290 2.4, which dvb-conformance does not emit), and SCTE-35 splice_insert cue-sanity checks, exported through the metrics facade for a host process to render as Prometheus.

Renamed crates

This project does not publish re-export shims. When a crate is renamed, every version under the old name is yanked, so an old Cargo.toml reference fails loudly instead of silently resolving to a frozen copy. Renamed so far: dvb-flute -> rmt-flute, smpte2038/dvb-smpte2038 -> st291, and ll-hls-runtime -> hls-runtime (this last one is the exception: its old versions are still live, because the rename tracked a scope change rather than a mistaken name).

For GSE, see the existing dvb-gse crate.

Docs-only directories (not crates)

cpix/ and st2110/ hold spec-transcription docs/ trees only — no Cargo.toml, no src/, not workspace members, and never published. They exist so a future crate has real, cited spec groundwork to start from.

Quickstart

Demux a .ts capture and print its SI sections — the dvb-tools dump CLI:

$ cargo run -p dvb-tools -- dump dvb-si/tests/fixtures/m6-single.ts
pid=0x0000 PROGRAM_ASSOCIATION v0 sn=0
pid=0x0064 PROGRAM_MAP v1 sn=0
-- packets=1264 sections=47 emitted=3 suppressed=44 crc_failures=0 malformed=0

$ cargo run -p dvb-tools -- dump dvb-si/tests/fixtures/m6-single.ts --json
{
  "pat": {
    "transport_stream_id": 1,
    "entries": [ { "program_number": 1025, "pid": 100 } ]
    // … (other fields elided for brevity)
  }
}

In code, the section-level pipeline is a feed-and-match loop:

use dvb_si::demux::SiDemux;
use dvb_si::descriptors::AnyDescriptor;
use dvb_si::tables::AnyTableSection;

let mut demux = SiDemux::builder().build();
for packet in ts_packets {                       // each aligned 188-byte packet
    for event in demux.feed(&packet) {           // changed sections only
        if let Ok(AnyTableSection::SdtSection(sdt)) = event.table_section() {
            for service in &sdt.services {
                for item in service.descriptors.iter().flatten() {
                    if let AnyDescriptor::Service(svc) = item {
                        println!("{}", svc.service_name.decode()); // Annex A → UTF-8
                    }
                }
            }
        }
    }
}

DVB System Software Update (SSU) chain

dvb-si ships complete end-to-end support for the DVB-SSU receiver chain (ETSI TS 102 006). Every layer is typed:

NIT linkage_descriptor (type 0x0A)
  └─▶ PMT data_broadcast_id_descriptor (tag 0x66, id = 0x000A)
         └─▶ IdSelector::Ssu → SsuIdSelector  (TS 102 006 §7.1 Table 4)
               UNT (table_id 0x4B) on the signalled PID
                 └─▶ UntPlatform × N (compatibilityDescriptor + descriptors)
                       DSM-CC carousel: DSI (messageId 0x1006) + DII + DDB
                         └─▶ GroupInfoIndication  (TS 102 006 §8.1.1 Table 6)
                               ModuleReassembler → complete firmware module bytes

To decode an SSU stream:

  1. Parse a NitSection; find a linkage_descriptor with linkage_type = 0x0A — it points to the network carrying the UNT.
  2. Parse the PmtSection for the SSU service; find a DataBroadcastIdDescriptor with data_broadcast_id = 0x000A. Its id_selector will be IdSelector::Ssu(SsuIdSelector { oui_entries, … }).
  3. The same PMT ES entry's PID carries UNT sections (table_id 0x4B). Parse UntSection; each UntPlatform describes a compatible device group with its own CompatibilityDescriptor and operational descriptors.
  4. Feed the carousel PID into SiDemux + DsmccSectionUnMessage::Dsi. Decode dsi.private_data as GroupInfoIndication::parse(dsi.private_data) to find the update groups and their sizes.
  5. Parse UnMessage::Dii to enumerate modules; feed DownloadDataBlock messages into ModuleReassembler to reconstruct complete firmware bytes.

Why these crates

These are not "good enough to parse the common case" parsers. The defining discipline is spec fidelity, verified several ways over:

  • Grounded in the ETSI deliverables. The PDFs are vendored in the repo and their syntax tables transcribed into reviewable markdown under dvb-si/docs/; every module doc cites its spec, section, and tag/table_id. No magic numbers — every hex literal outside tests is a named constant or enum.
  • Symmetric and round-trip tested — these crates emit as well as parse. Every table and descriptor implements Serialize, not just Parse: build a PatSection / PmtSection / CaDescriptor and call serialize_into to get a complete section (CRC-32 included). Parse → serialize → parse is byte-identical, a hard project invariant enforced by tests. So there's no need to hand-roll PSI encoders.
  • Decoded, not just typed. Spec-enumerated codes are typed enums with decoded names — running_status is a RunningStatus, stream_type a StreamType, service_type a ServiceType; content genre, parental-rating age, AC-3/E-AC-3 (0x6A/0x7A typed descriptors), and more decode in the library, so consumers never re-implement an ETSI lookup table.
  • Five adversarial spec-audit rounds against the transcriptions, plus fixture tests run against real transponder captures (e.g. a live French TNT / M6 HbbTV mux; a 10 s satellite capture decoding "Emission Spéciale Politique" out of an EIT).
  • Complete coverage. Every allocated table_id in EN 300 468 V1.19.1 Table 2 and every descriptor_tag in Table 12; all 12 T2-MI packet types.

Documentation

License

Licensed under either of MIT or Apache-2.0, at your option. Contributions are accepted under the same dual license.

About

Rust crates for DVB protocols — SI (EN 300 468), T2-MI (TS 102 773), BBFRAME (EN 302 307), and shared primitives. Private until content review complete.

Resources

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages