dvb-conformance 9.1.1

ETSI TR 101 290 transport-stream conformance monitor (DVB measurement guidelines).
Documentation

dvb-conformance

crates.io docs.rs License

ETSI TR 101 290 v1.4.1 transport-stream conformance monitor (DVB measurement guidelines). Feed TS packets with a caller-supplied monotonic clock, drain structured conformance events per indicator.

Quick start

use dvb_conformance::{ConformanceMonitor, ConformanceEvent, Indicator};
use core::time::Duration;

let mut monitor = ConformanceMonitor::new();  // default config

let mut t = Duration::ZERO;
for packet in ts_packets {
    t += Duration::from_micros(188 * 8 * 1_000_000 / 6_000_000); // ≈188 bytes @ 6 Mbit/s
    for event in monitor.feed(packet, t) {
        eprintln!("[{:?}] {}: {}", event.priority, event.indicator.name(), event.detail);
    }
}

Use ConformanceMonitor::with_config(Config { .. }) to tune thresholds (PAT/PMT max intervals, PCR repetition and discontinuity limits, SI repetition intervals, etc.).

What's implemented

Indicators — 19 implemented, per the Indicator enum in src/lib.rs

Priority Clause Indicator Notes
1 1.1 TsSyncLoss Hysteresis: 5 consecutive good → in-sync; 2 consecutive bad → sync lost
1 1.2 SyncByteError sync_byte != 0x47 on any packet
1 1.3.a PatError2 PAT absent > 500 ms (default); wrong table_id or scrambled on PID 0x0000
1 1.4 ContinuityCountError CC wrap + duplicate-packet allowance (one dup per sequence)
1 1.5.a PmtError2 PMT absent > 500 ms per program_map_PID; scrambled on PMT PID
1 1.6 PidError Referenced ES PID absent > 5 s (default)
2 2.1 TransportError transport_error_indicator set
2 2.2 CrcError CRC-32 mismatch on completed long-form SI/PSI section
2 2.3a PcrRepetitionError PCR interval > 100 ms (default) on any PCR-carrying PID
2 2.3b PcrDiscontinuityError PCR delta > 100 ms (default) without discontinuity_indicator
2 2.5 PtsError PTS interval > 700 ms (default) on ES PIDs
2 2.6 CatError Wrong table_id on PID 0x0001; scrambled packet with no CAT seen
3 3.1 NitError Bad table_id on PID 0x0010 (not NIT_actual/NIT_other/ST); NIT_actual absent > 10 s (default)
3 3.2 SiRepetitionError Max-interval dimension: NIT_actual (10 s), SDT_actual (2 s), EIT P/F actual (2 s), TDT (30 s)
3 3.4 UnreferencedPid A PID persists > 500 ms (default) without being referenced by the PAT/CAT/a PMT or a well-known SI PID
3 3.5 SdtError Bad table_id on PID 0x0011 (not SDT_actual/SDT_other/BAT/ST); SDT_actual absent > 2 s (default)
3 3.6 EitError Bad table_id on PID 0x0012 (not EIT P/F or schedule range 0x50–0x6F or ST); EIT P/F actual absent > 2 s (default)
3 3.7 RstError Bad table_id on PID 0x0013 (not RST/ST)
3 3.8 TdtError Bad table_id on PID 0x0014 (not TDT/TOT/ST); TDT absent > 30 s (default)

New indicators (T-STD, #737)

Priority Clause Indicator Notes
2 2.4 PcrAccuracyError Not implemented — requires hardware arrival timing with ±500 ns resolution (ISO/IEC 13818-1 §2.4.2.2); the variant exists for documentation completeness only; never emitted
3 3.3 BufferError TBsys overflow (512-byte buffer, 1 Mbit/s drain); TBn overflow deferred (needs coded bitrate Rxn from descriptors)
3 3.9 EmptyBufferError TBn/TBsys empty at least once per second; MBn check deferred (needs leak-method parameters from descriptors)
3 3.10 DataDelayError Data delay through T-STD transport buffers > 1 s; still-picture 60 s threshold NOT implemented — requires PMT stream_type detection from descriptors

T-STD buffer model (#737)

A partial ISO/IEC 13818-1 T-STD buffer model (see src/tstd.rs) drives indicators 3.3, 3.9, and 3.10:

  • TBn (per-PID, 512 bytes): modelled for empty-interval and data-delay tracking. Overflow detection is deferred — it requires the coded bitrate Rxn from descriptors (multiplex_buffer_descriptor).
  • TBsys (global, 512 bytes, 1 Mbit/s drain): fed at PSI section completion. Overflow (firewall), empty-interval, and data-delay checks are implemented.
  • MBn / EBn / Bn / Bsys: deferred — these require codec-level buffer sizes from descriptors and are not yet parsed by the monitor.

All buffer sizes and rates are named constants citing the vendored ITU-T H.222.0 v9 (08/2023) PDF. The full transcription is at dvb-conformance/docs/h222_0-tstd-buffer-model.md.

Constant Value H.222.0 clause
TBn / TBsys size 512 bytes §2.4.2.4, p.42: "The transport buffer size is fixed at 512 bytes"
TBsys drain rate 1 Mbit/s §2.4.2.4, p.42: "For systems data: Rxn = 1×10⁶ bits per second"
Bsys size 1536 bytes §2.4.2.4, p.43: "The main buffer Bsys … size BSsys = 1536 bytes" (deferred)
TB leak rate floor 125 kbit/s Modelling floor, not a spec value (Rxn ≥ 2×10⁶ bps per §2.4.2.4)

Note on 2.4 PCR_accuracy_error: this indicator requires hardware arrival timestamps with ±500 ns accuracy. The monitor is sans-IO with a caller-supplied clock; a packet-index-derived timing estimate cannot honestly resolve 500 ns. A false positive here is worse than a gap (cf. the withdrawn PtsCheck). The indicator exists in the enum for documentation completeness but is never emitted.

Excluded, split by reason:

Not computable without hardware arrival timing (needs ±500 ns resolution):

Clause Indicator Reason
2.4 PCR_accuracy_error Requires ±500 ns PCR accuracy measurement against a hardware reference clock (ISO/IEC 13818-1 §2.4.2.2); a packet-index-derived arrival estimate cannot resolve 500 ns

Partially implemented — TBn overflow / MBn / EBn / Bn / Bsys deferred (needs codec-dependent buffer-size descriptors not yet parsed by the monitor):

Clause Indicator Deferred sub-checks
3.3 Buffer_error TBn overflow (needs Rxn from descriptors); MBn/EBn/Bn underflow/overflow; Bsys overflow
3.9 Empty_buffer_error MBn empty-at-least-once-per-second (leak method)
3.10 Data_delay_error Still-picture video data 60 s threshold differentiation; MBn delay

Feasible, deferred (reusable with the existing timer machinery, but not yet implemented):

Clause Indicator Reason
3.1.a / 3.2 / 3.5.a / 3.6.a / 3.7 / 3.8 (25 ms min-gap dimension) Needs per-(table_id, section_number) tracking to avoid false positives on dense multi-section tables
3.1.b / 3.5.b / 3.6.b NIT_other_error / SDT_other_error / EIT_other_error Need TR 101 211 _other repetition interval rules
3.6.c EIT_PF_error EIT P/F section-0/1 pairing check not yet implemented

Caller-supplied time model

ConformanceMonitor::feed(packet, t) takes a core::time::Duration alongside each TS packet. The monitor uses this clock for all presence/absence timeout checks (1.3.a, 1.5.a, 1.6, 2.3a, 2.3b, 2.5, 3.2). The caller must supply monotonic non-decreasing timestamps; the monitor does not enforce this but non-monotonic timestamps will produce spurious events. Because there is no independent hardware clock, PCR accuracy (2.4) and buffer-model indicators are not computable.

SI_repetition_error (3.2) — implementation notes

  • Maximum-interval checks are implemented for NIT_actual (10 s), SDT_actual (2 s), EIT P/F actual (2 s), and TDT (30 s). Each table's timer is lazily armed — checking starts only after the first section of that table is seen; an entirely absent table is not flagged by this indicator (that is the role of the out-of-scope per-table presence indicators).
  • EIT P/F is tracked at the table level (any section with table_id 0x4E resets the timer), not per section_number, to avoid false positives on dense EIT schedules.

PAT-following PMT discovery

The monitor parses each completed PAT section and automatically starts tracking the program_map_PID entries it finds, enabling indicator 1.5.a (PMT absence) and ES PID extraction (indicator 1.6).

NIT/SDT/EIT/RST/TDT_error (3.1, 3.5, 3.6, 3.7, 3.8) — implementation notes

  • Each indicator validates the table_id of every completed section on its well-known PID against the allowed set from docs/tr_101_290.md clause 3.x, firing immediately on a disallowed value.
  • The absence dimension of 3.1/3.5/3.6/3.8 (NIT_actual/SDT_actual/EIT P/F actual/TDT missing beyond the repetition interval) is raised from the same lazily-armed timer that drives SiRepetitionError (3.2) — the two indicators are the same underlying absence event with two spec identities (the old combined indicator vs. the newer split _actual variant); both fire together.
  • RstError (3.7) has no documented absence threshold in Table 5.0c, so it only has the bad-table_id dimension.

Unreferenced_PID (3.4) — implementation notes

  • Tracks the first-seen time of any PID that is not (yet) part of the referenced set: PAT, CAT, the well-known SI PIDs (NIT/SDT-BAT/EIT/RST/ TDT-TOT), the null PID, the reserved-for-future-use range (0x0002–0x000F), program_map_PIDs from the PAT, and ES/PCR PIDs from a PMT. A PID that persists past the 500 ms (default) threshold without becoming referenced raises UnreferencedPid.
  • Known limitations (documented, not silently swallowed): CAT-referenced EMM PIDs are not exempted — this monitor validates CAT table_id but does not decode CA descriptors to extract CA_PIDs. PIDs "user defined as private data streams" (the spec's own carve-out) are likewise not distinguishable from the wire alone. Either can produce a false positive for a stream using that pattern; the crate does not currently model it.

Feature flags

Feature Default Description
std on Link the standard library. Without it the crate is #![no_std] + alloc.
serde on Serialize-only (serde::Serialize) on ConformanceEvent, Indicator, Priority, Stats.

MSRV

Rust 1.86.

References

  • ETSI TR 101 290 v1.4.1 (2020-06) — DVB Measurement Guidelines (§5.2.1 Table 5.0a, §5.2.2 Table 5.0b, §5.2.3 Table 5.0c)
  • ISO/IEC 13818-1 — MPEG-2 Systems

Examples

Run with cargo run -p dvb-conformance --example <name>:

  • monitor_stream — run the TR 101 290 monitor over a capture and print the headline stats.
  • priority_breakdown — tally findings by measurement priority (1/2/3) and indicator.

License

Licensed under either of MIT (LICENSE-MIT) or Apache-2.0 (LICENSE-APACHE), at your option.