mirror of
https://github.com/freemkv/libfreemkv.git
synced 2026-10-07 18:13:10 +00:00
Security - Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged. CI / tooling - clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny dependency-audit gate with first-party git sources allowed (#15); audience-based comment-guard (#17). Docs - README (keydb ownership, BD-J parser count), drive-access transport/reset notes, mux timeline module-doc links.
70 lines
3.3 KiB
Markdown
70 lines
3.3 KiB
Markdown
# `dropgate` — audio drop bookkeeping rationale
|
|
|
|
## Keep/drop rule
|
|
|
|
A clean mux keeps every frame it can and drops the ones it can't — video
|
|
always survives (it's inter-frame predicted; a per-frame drop would cascade,
|
|
so video resyncs/conceals instead), audio keeps every decodable access unit,
|
|
and a damaged audio AU is dropped rather than shipped as a decoder-choking
|
|
glitch.
|
|
|
|
## Detection is per-codec
|
|
|
|
The DETECTION is inherently per-codec — each format carries its own
|
|
authoritative corruption check (DTS: the core sync/header parse per ETSI TS
|
|
102 114; AC-3: the header CRC per ETSI TS 102 366; FLAC: the frame CRC-16;
|
|
…). `DropTally` only carries the UNIFORM response so every audio parser
|
|
behaves identically:
|
|
|
|
1. **Count** kept vs dropped AUs and the dropped duration.
|
|
2. **Log** every drop (fail-loud, never silent) — a per-drop trace plus a
|
|
once-per-track aggregate at `warn` so it surfaces without debug logging.
|
|
3. **Whole-track fallback**: once a track is judged mostly undecodable, latch
|
|
a poison flag so the remainder is dropped too (a track that damaged isn't
|
|
worth muxing).
|
|
|
|
## Sync preservation
|
|
|
|
**Sync preservation is the caller's responsibility**, not this type's: the
|
|
parser must advance its PTS clock across a dropped AU exactly as it would for
|
|
an emitted one, so a drop becomes a silence gap and never a shift of the
|
|
following audio. See `DtsParser`'s `stamp_pts` call ordering for the pattern.
|
|
|
|
## `verified_dropped` vs `dropped`
|
|
|
|
`verified_dropped` counts AUs dropped because they were INDIVIDUALLY verified
|
|
undecodable (a failed CRC/header/parity check); only these feed the
|
|
whole-track poison verdict. `dropped` also counts *collateral* drops — AUs
|
|
discarded as a consequence of one corruption (TrueHD's resync-forward run, or
|
|
a poisoned track) — which must NOT amplify a few real errors into a false
|
|
whole-track loss.
|
|
|
|
## `record_collateral_drop`
|
|
|
|
A collateral drop is caused by another AU's corruption (TrueHD's
|
|
resync-forward run to the next major sync, or an already-poisoned track), not
|
|
by being individually verified undecodable. It is counted and logged for the
|
|
drop report, but deliberately does NOT feed the poison verdict, so one
|
|
corruption event can't amplify into a false whole-track loss.
|
|
|
|
## `maybe_poison`
|
|
|
|
Whole-track fallback: after enough AUs to judge, if more than half were
|
|
dropped the track is too damaged to be worth muxing — latch `poisoned` and
|
|
log it loudly once. The minimum-sample gate keeps a short damaged burst from
|
|
poisoning an otherwise-good track. Judge on VERIFIED drops vs all AUs seen: a
|
|
track is only poisoned when a majority of its access units are individually
|
|
undecodable — not when a couple of corruption events forced long collateral
|
|
resync runs.
|
|
|
|
## Test: `interleaved_keeps_are_in_the_poison_denominator`
|
|
|
|
The poison verdict is a RATIO — verified drops against every AU seen — so
|
|
the kept count is half of it. `does_not_poison_a_mostly_good_track` records
|
|
its keeps AFTER the single drop, and `maybe_poison` only runs inside
|
|
`record_drop`, so the keeps are never in the denominator when the verdict is
|
|
actually computed: that test passes even with the kept count never
|
|
incremented. Interleaving them puts the kept count on the critical path,
|
|
where losing it turns the ratio into "verified drops vs verified drops" —
|
|
always >50% — and silently discards a healthy track.
|