# Changelog
## [Unreleased]
## [10.0.0] - 2026-08-11
### Changed
- `check_cc`'s legal-duplicate detection (the #956 fix below) now delegates
to the new shared `broadcast_common::ts_dup` (`is_legal_duplicate_pair` /
`check_duplicate`), replacing the local `canonical_packet_for_dup_check`.
No behaviour change — same byte-identity-except-PCR comparison, same
"two, and only two consecutive" `dup_used` state machine, verified by this
crate's existing test suite passing unchanged. Consolidates what used to
be three independently hand-rolled, disagreeing copies of ITU-T H.222.0
§2.4.3.3 (`dvb-conformance`, `media-doctor`, `ts-fix`) into one.
- **Correction to the #956 note below**: that note claimed `media-doctor`
"already implemented the payload-comparison rule correctly" — it did
not. `media-doctor`'s `CcAnomalyCheck` compared only the elementary-
stream payload slice, which would have accepted a changed
`splice_countdown` or OPCR as a legal duplicate, and never enforced the
"two, and only two" cardinality rule at all (an unbounded run of
byte-identical repeats was silently accepted). Both are fixed in
`media-doctor`'s own CHANGELOG, delegating to the same shared function.
- This crate's own property (2) (`adaptation_field_control` must be `01`
or `11`) and property (3) ("two, and only two consecutive") were
already correctly enforced before #956 — that fix addressed property
(1) (byte-identity, PCR excepted) only. Confirmed by reading `check_cc`
prior to this change: property (2) via the pre-existing
`header.has_payload` gate (`AdaptationFieldControl::from_flags` maps
`has_payload == true` to exactly AFC `01`/`11`), property (3) via the
pre-existing `dup_used` flag emitting a second `Continuity_count_error`
on a third consecutive repeat.
### Fixed
- **`Continuity_count_error` (1.4) under-reported legal duplicates** (issue
#956). The check treated ANY packet repeating the previous
`continuity_counter` on a PID as a legal duplicate — it never compared
payload bytes. Per ISO/IEC 13818-1:2023 §2.4.3.3 ("In duplicate packets
each byte of the original packet shall be duplicated, with the exception
that in the program clock reference fields, if present, a valid value
shall be encoded"), a same-CC repeat is legal only when it is
byte-identical to its predecessor apart from a re-encoded PCR field. Any
other same-CC repeat is a genuine continuity fault that was previously
silent.
- **Behaviour change**: a stream this monitor previously reported clean
(zero indicator-1.4 events) may now report `Continuity_count_error` —
correctly. This is not a false positive: the new events fire only on
packets that repeat a CC with a payload that has genuinely changed. On
the committed `m6-duplicate.ts` fixture, the fixed monitor now
distinguishes 5 genuine legal duplicates (still silent) from 77 real
same-CC/different-payload repeats (now flagged) that the old code
silently absorbed into "duplicate". The `m6-single.ts` fixture carries
the same pattern: its `Continuity_count_error` count under
`ConformanceMonitor` rises from 803 to 876 (confirmed by running
`compliance-probe`'s test suite against this fix). That crate's
`tests/wasm_analyzer_equivalence.rs` pins the old 803/838 figures against
a reference WASM analyzer that shares this same class of bug — it is now
failing as expected and needs its pinned numbers (and the matching
`838 events vs. 803` prose in `compliance-probe/src/lib.rs`'s module
docs) updated when that crate picks up this fix; left untouched here as
out of this crate's scope.
- Per-PID memory cost increases by up to one TS packet's worth of bytes
(`Vec<u8>`, ≤188 bytes) to retain the previous packet for the
byte-identity comparison; this is bounded per distinct PID, not
per-packet.
- Brings this crate's rule in line with `media-doctor`'s
`CcAnomalyCheck`, which already implemented the payload-comparison rule
correctly (`media-doctor/src/diagnostics/cc_anomaly.rs`) — the two
crates previously disagreed on the same stream.
### Changed
- MSRV raised to **1.95.0** (issue #949). This removes the workspace's MSRV
split: `webrtc-runtime`'s optional `media` feature needed rustc 1.88 (via
`rcgen`), which had grown a dedicated CI job, six `--exclude` lanes and a
guard script to contain. Adopting let-chains and `is_multiple_of` where the
1.95 lints require them; no functional or API change.
## [9.2.0] - 2026-08-05
### Added
- Five new TR 101 290 v1.4.1 Priority-3 indicators (#736):
- `SiMinGapError` — 25 ms minimum-gap violation between sections of the same
`(table_id, section_number)` on the same PID, shared by dimensions 3.1.a /
3.2 / 3.5.a / 3.6.a / 3.7 / 3.8. Tracked per-`(table_id, section_number)`,
not per `table_id`, to avoid false positives on dense multi-section tables.
- `NitOtherError` (3.1.b) — NIT_other (0x41) sections with same
`section_number` > 10 s apart on PID 0x0010
- `SdtOtherError` (3.5.b) — SDT_other (0x46) sections with same
`section_number` > 10 s apart on PID 0x0011
- `EitOtherError` (3.6.b) — EIT P/F other (0x4F) sections with same
`section_number` > 10 s apart on PID 0x0012
- `EitPfError` (3.6.c) — EIT P/F sub-table missing one of its two sections;
per-sub-table (`service_id, transport_stream_id, original_network_id`),
not global
- `_other` repetition checks only fire after the sub-table's presence is
established (observed at least twice), so streams that legitimately carry no
`_other` table are never flagged.
- New `Config` fields: `si_min_gap` (default 25 ms), `si_other_interval`
(default 10 s per ETSI TR 101 211 §4.4)
## [9.1.1] - 2026-07-30
### Fixed
- Floor `mpeg-ts` to `0.3.1`. The `^0.3` bucket also contains 0.3.0, which is
built against `broadcast-common` 8, so a consumer could resolve two
`broadcast-common` majors into one graph and hit trait-resolution errors
pointing at this crate's internals (#858).
## [9.1.0] - 2026-07-30
### Added
- T-STD buffer model and four new indicators (#737):
- `BufferError` (3.3): TBsys overflow detection; TBn overflow deferred
- `EmptyBufferError` (3.9): TBn/TBsys empty-at-least-once-per-second
- `DataDelayError` (3.10): data delay > 1 s through transport buffers
- `PcrAccuracyError` (2.4): documented as not implemented (needs ±500 ns hardware timing)
- Partial ISO/IEC 13818-1 T-STD buffer model in `src/tstd.rs`:
- Per-PID TBn (512 bytes) with dynamic leak-rate estimation
- Global TBsys (512 bytes, 1 Mbit/s drain) fed at PSI section completion
- Named constants with spec citations for all buffer sizes and rates
- TBsy overflow fires `BufferError` when a completed PSI section exceeds
the 512-byte capacity with insufficient drain time
### Changed
- `Indicator` enum is now `#[non_exhaustive]` with 4 new variants
- Indicator-coverage documentation updated in README, docs/tr_101_290.md,
and lib.rs module doc
## [9.0.0] - 2026-07-27
### Changed (Breaking)
- Lockstep major bump alongside `broadcast-common` 9.0.0, whose `Encrypt::encrypt`
now takes `&mut self` instead of `&self` (needed so a stateful implementor can
own a running per-key IV counter — see `broadcast-common`'s own CHANGELOG for
the full rationale and the migration note for external `impl Encrypt`s).
`dvb-conformance` itself does not implement `Encrypt`/`Decrypt` and has no
functional or public API change of its own in this release.
## [8.6.0] - 2026-07-22
### Added
- TR 101 290 v1.4.1 Table 5.0c Priority-3 indicators (#732): `NitError` (3.1),
`UnreferencedPid` (3.4), `SdtError` (3.5), `EitError` (3.6), `RstError`
(3.7), `TdtError` (3.8) — bad-`table_id` checks on PID 0x0010/0x0011/
0x0012/0x0013/0x0014, plus the presence/absence dimension for NIT_actual/
SDT_actual/EIT P/F actual/TDT sharing the existing 3.2 SI-repetition timer.
New `PID_RST` (0x0013) well-known PID; new `Config::unreferenced_pid_period`
(default 500 ms). `Indicator` gains 6 new `#[non_exhaustive]` variants —
additive, no breaking change. See `docs/tr_101_290.md` for the full spec
transcription and per-clause coverage mapping.
## [8.5.0] - 2026-07-21
### Changed
- Internal: consume renamed `mpeg-ts` 0.3 `mux::SectionPacketiser` (was
`SectionPacketizer`) in the crate's own test helpers; widen the internal
`mpeg-ts` dependency to `0.3` (issue #663). No public API change to
`dvb-conformance`.
## [8.4.0] - 2026-07-03
### Changed
- Rust **edition 2024**; MSRV raised to **1.86**; format-argument modernisation. No functional or API change.
## [8.3.0] - 2026-07-03
### Changed
- Lockstep release with the DVB core crates; no functional changes to `dvb-conformance`.
## [8.2.1] — 2026-07-02
### Changed
- Lockstep release tracking `broadcast-common` 8.2.1 (mux-trait documentation). No API/behaviour change to this crate.
## [8.2.0] — 2026-07-02
### Changed
- Lockstep release tracking `broadcast-common` 8.2.0 (new `mux` container-mux
traits). No API or behavioural change to this crate.
## [8.1.0] — 2026-06-29
### Changed
- Lockstep release. Internal dependency `dvb-common` renamed to `broadcast-common`; no API change.
## [8.0.0] — 2026-06-27
### Changed
- Lockstep major release; parity bump. Now depends on `mpeg-ts` transitively
via `dvb-si` for TS framing. No API changes.
## [7.9.0] — 2026-06-22
### Changed
- Lockstep release; no functional changes to this crate.
## [7.8.0] — 2026-06-21
### Changed
- Lockstep release; no functional changes to this crate.
## [7.7.1] — 2026-06-21
### Changed
- Lockstep release; no functional changes to this crate.
## [7.7.0] — 2026-06-20
### Changed
- Lockstep release; no functional changes to this crate.
## [7.6.0] — 2026-06-20
### Changed
- Lockstep release; no functional changes to this crate.
## [7.5.0] — 2026-06-19
### Added
- `examples/`: `monitor_stream` (run the TR 101 290 monitor over a capture) and
`priority_breakdown` (tally findings by measurement priority + indicator).
## [7.4.0] — 2026-06-18
Lockstep release; no functional changes.
## [7.3.0] — 2026-06-17
### Changed
- Lockstep release; no functional changes to this crate.
## [7.2.0] — 2026-06-16
### Changed
- Lockstep release; no functional changes to this crate.
## [7.1.0] — 2026-06-15
### Changed
- Lockstep release; rebuilt against the dvb-* parser-hardening pass (#207). No
functional changes.
## [7.0.0] — 2026-06-14
**BREAKING (MSRV 1.75 → 1.81).**
### Added
- **no_std + alloc support** (#63; HashMap→BTreeMap).
### Changed (breaking)
- MSRV **1.81**.
## [6.7.0] — 2026-06-14
### Added
- `Display` on `Priority` and `Indicator`, and `name()` on `Priority`, via
`impl_spec_display!`; `label_coverage` drift-guard test (#204).
## [6.6.0] — 2026-06-14
Version-lockstep release with the workspace (dvb-t2mi L1-pre/L1-post signalling parser #54; dvb-si BIOP object-carousel layer #64; criterion benchmark suites #62). No changes to this crate.
## [6.5.0] — 2026-06-13
Version-lockstep release with the workspace (#47 T2 emission-time accessors; #50 SSU GroupInfoIndication + data_broadcast_id 0x000A selector; #53 S2Xv2 0x24 extension descriptor). No changes to this crate.
## [6.4.0] — 2026-06-13
Version-lockstep release with the workspace (#158 spec-table drift-guards + spec-fidelity audit; dvb-si PMT section/last-section fields; dvb-bbframe DVB-S2 BUFSTAT ISSY decode). No changes to this crate.
## [6.3.0] — 2026-06-13
Version-lockstep release with the workspace (new `dvb-scte35` crate; dvb-si `TsResync` byte-stream resync helper). No changes to this crate.
## [6.2.0] — 2026-06-13
### Added
- New crate `dvb-conformance`: ETSI TR 101 290 v1.4.1 transport-stream
conformance monitor (#57).
- Priority-1 indicator set implemented: `TS_sync_loss` (1.1),
`Sync_byte_error` (1.2), `PAT_error_2` (1.3.a),
`Continuity_count_error` (1.4), `PMT_error_2` (1.5.a),
`PID_error` (1.6).
- Priority-2 indicator set implemented: `Transport_error` (2.1),
`CRC_error` (2.2), `PCR_repetition_error` (2.3a),
`PCR_discontinuity_indicator_error` (2.3b), `PTS_error` (2.5),
`CAT_error` (2.6).
- Indicator 2.4 (`PCR_accuracy_error`) is intentionally not implemented: the
±500 ns spec tolerance requires hardware arrival timestamps, which are not
available under the caller-supplied-time model.
- Priority-3 indicator `SI_repetition_error` (3.2, maximum-interval dimension)
implemented for NIT_actual (10 s), SDT_actual (2 s), EIT P/F actual (2 s),
and TDT (30 s). Timers are lazily armed — checking starts only after the
first section of each table is seen.
- The 25 ms minimum-gap dimension of indicator 3.2 is deferred: it needs
per-`(table_id, section_number)` tracking to avoid false positives on dense
multi-section tables.
- CRC checking generalised across all well-known SI/PSI PIDs (PAT, CAT, NIT,
SDT/BAT, EIT, TDT/TOT) plus dynamically discovered PMT PIDs.
- Configurable PCR repetition, PCR discontinuity, and PTS repetition limits
via new `Config` fields.
- Configurable SI repetition intervals (`si_nit_interval`, `si_sdt_interval`,
`si_eit_pf_interval`, `si_tdt_interval`) via new `Config` fields.
- Caller-supplied-time model: `ConformanceMonitor::feed(packet, t)` takes a
monotonic `Duration` timestamp per packet for all timeout checks.
- Configurable hysteresis and timeout parameters via `Config`.