Skip to main content

Crate dvb_t2mi

Crate dvb_t2mi 

Source
Expand description

ETSI TS 102 773 v1.4.1 DVB-T2 Modulator Interface (T2-MI) parser + builder.

Entry points:

§RFU policy

Payload parsers REJECT non-zero reserved (rfu) bits with ReservedBitsViolation and serialize them as 0 — with one deliberate exception: individual addressing (0x21) PRESERVES its leading rfu byte verbatim so gateway streams round-trip byte-exact (see payload::individual_addressing).

§Quickstart: pump a TS, get typed payloads

pump::T2miPump filters a TS by PID, reassembles + CRC-validates T2-MI packets, and hands back events whose payload dispatches to a typed payload::AnyPayload:

use dvb_t2mi::pump::T2miPump;
use dvb_t2mi::payload::AnyPayload;

let mut pump = T2miPump::new(0x0006); // T2-MI PID from the PMT
for packet in &ts_packets {          // each aligned 188-byte TS packet
    for event in pump.feed_ts(packet) {
        if let Ok(AnyPayload::Bbframe(bb)) = event.payload() {
            println!("BBFrame plp_id={}", bb.plp_id);
        }
    }
}

§The full signal chain

T2-MI carries DVB-T2 BBFrames, which carry the inner MPEG-TS, which carries SI. The crates compose end to end — T2-MI here, BBFrame extraction in dvb-bbframe, SI demux in dvb-si:

TS (T2-MI PID) ─▶ T2miPump ─▶ AnyPayload::Bbframe
                                  │ bb.bbframe
                                  ▼
                         dvb_bbframe::Bbheader::parse + up_iter
                                  │ inner TS packets
                                  ▼
                         dvb_si::demux::SiDemux ─▶ AnyTableSection

A complete, working version of this chain (synthetic fixture, every layer built and asserted) lives in dvb-t2mi/tests/chain.rs.

§Features

FeatureDefaultEnables
tsonpump::T2miPump — PID-filtered TS reassembly + CRC validation. Off → bring your own complete T2-MI packet bytes.
serdeonSerialize-only — for display/export (JSON via serde_json); parsing FROM JSON is deliberately unsupported, re-parse from wire bytes. Serialize on every packet/payload type.
yokeoffyoke::Yokeable on the zero-copy payload view types — own a parsed T2-MI payload past the input buffer’s borrow without re-parsing.

§Header-only example

use dvb_t2mi::packet::Header;
use broadcast_common::Parse;
let buf = [0x00u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
let hdr = Header::parse(&buf[..]).unwrap();
assert_eq!(hdr.payload_len_bits, 0);

§Examples

Two runnable examples ship with this crate (cargo run -p dvb-t2mi --example <name>).

§parse_header

//! Basic: parse a T2-MI packet header from raw bytes.
//!
//! Run with: `cargo run -p dvb-t2mi --example parse_header`

use broadcast_common::Parse;
use dvb_t2mi::packet::Header;

fn main() {
    // A 6-byte T2-MI packet header: packet_type, packet_count, superframe_idx,
    // reserved, and a 16-bit payload length in bits (here: 0).
    let bytes = [0x00u8, 0x00, 0x00, 0x00, 0x00, 0x00];

    let hdr = Header::parse(&bytes).expect("valid T2-MI header");

    println!("packet_type     : {:?}", hdr.packet_type);
    println!("packet_count    : {}", hdr.packet_count);
    println!("superframe_idx  : {}", hdr.superframe_idx);
    println!("payload_len_bits: {}", hdr.payload_len_bits);
}

§pump_capture

//! Advanced: pump a real T2-MI stream out of an MPEG-TS capture and tally the
//! payload types (BBFrames, L1 signalling, timestamps).
//!
//! Run with: `cargo run -p dvb-t2mi --example pump_capture` (needs the default
//! `ts` feature). Reads the committed `colombia-capital-t2mi.ts` fixture at
//! runtime.

use dvb_t2mi::payload::AnyPayload;
use dvb_t2mi::pump::T2miPump;

const T2MI_PID: u16 = 0x0040;
const PKT: usize = 188;

fn main() {
    // Fixtures live in the workspace-shared `fixtures/` tree, not under the
    // crate. A committed fixture that cannot be read is a bug, not a reason
    // to skip — so a missing/unreadable fixture is a hard failure.
    let path = concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/../fixtures/dvb-t2mi/colombia-capital-t2mi.ts"
    );
    let data = std::fs::read(path)
        .unwrap_or_else(|e| panic!("committed fixture {path} could not be read: {e}"));

    let mut pump = T2miPump::new(T2MI_PID);
    let (mut bbframes, mut l1, mut timestamps, mut other) = (0u32, 0u32, 0u32, 0u32);

    for pkt in data.chunks(PKT) {
        if pkt.len() < PKT {
            break;
        }
        for event in pump.feed_ts(pkt) {
            match event.payload() {
                Ok(AnyPayload::Bbframe(_)) => bbframes += 1,
                Ok(AnyPayload::L1Current(_)) => l1 += 1,
                Ok(AnyPayload::Timestamp(_)) => timestamps += 1,
                Ok(_) => other += 1,
                Err(_) => {}
            }
        }
    }

    println!("T2-MI on PID {T2MI_PID:#06X}:");
    println!("  BBFrame payloads   : {bbframes}");
    println!("  L1-current packets : {l1}");
    println!("  timestamp packets  : {timestamps}");
    println!("  other payloads     : {other}");
    println!("  CRC-32 failures    : {}", pump.stats().crc_failures);
}

Re-exports§

pub use error::Error;
pub use error::Result;

Modules§

crc
T2-MI CRC helpers.
error
Error type returned by every parser in this crate.
inner_tsts
Inner-TS recovery — the single driver from a T2-MI PID to the inner MPEG-TS.
packet
T2-MI packet header and type parsing.
payload
T2-MI payload types (§5.2.1 - §5.2.12).
pumpts
T2miPump — owning-Bytes feed-and-iterate T2-MI pump.
traits
T2-MI–specific traits. Parse / Serialize are provided by broadcast_common and imported directly at call sites.
tsts
TS packet reassembly utilities.