Expand description
Robust media container-format detection over a caller-owned byte slice.
container-probe identifies whether a byte prefix (a file’s leading bytes,
a network read) is an MPEG-2 Transport Stream, an ISOBMFF file, a
Matroska/WebM file, MXF, MPEG—PS, FLV, WAV, Ogg, ASF, or a raw ADTS AAC /
MP3 / Annex B elementary stream. One-shot over a slice: the crate holds no
buffer, owns no IO, and keeps no state.
§Detected formats
| Format | How it is detected | Best confidence tier |
|---|---|---|
| MPEG-2 TS | sync lattice over 188/192/204/208-byte strides | LATTICE_STRONG |
| ISOBMFF | box-chain walk (ISO/IEC 14496-12 §4.2) | STRUCTURAL |
| Matroska/WebM | EBML magic + DocType | CERTAIN |
| MXF | partition-pack key + BER length | CERTAIN |
| MPEG-PS | pack start code + marker bits | STRUCTURAL |
| FLV | "FLV" signature + header fields | STRONG |
| WAV | "RIFF".."WAVE" | STRONG |
| Ogg | "OggS" | STRONG |
| ASF | 16-byte header GUID | STRONG |
| ADTS AAC | frame-length chain | LATTICE_STRONG |
| MP3 | frame-length chain | LATTICE_STRONG |
| Annex B (H.264) | start-code NAL chain | LATTICE_STRONG |
§Known gaps
- Annex B detection is H.264 only. HEVC (H.265) NAL units use a 2-byte
header with
nal_unit_typeat bits[6:1], which this prober does not parse — it validates the H.264 1-byte header, so an HEVC stream fails the range check at the first NAL. HEVC is deliberately not implemented: this workspace does not implement a format without a real fixture to test it against, and no HEVC Annex B fixture exists in the repository.
§The scored confidence model
Every registered prober runs over the same bytes and returns a scored
candidate (an Evidence): a Confidence tier and a Detail. All probers
always run, so the answer does not depend on declaration order. The
highest score wins:
| Tier | Value | Meaning |
|---|---|---|
CERTAIN | 240 | Magic plus a structural confirmation |
STRONG | 192 | Unambiguous magic at a defined offset |
STRUCTURAL | 160 | A validated structure chain |
LATTICE_STRONG | 128 | >= 8 lattice/frame confirmations |
LATTICE_WEAK | 96 | 3-7 lattice/frame confirmations |
HEURISTIC | 64 | A signature with real false-positive risk |
If the top two candidates are within TIE_THRESHOLD (16), the result is
Probe::Ambiguous with every candidate listed — never an arbitrary pick.
A container matched at LATTICE_STRONG or above zeroes every
elementary-stream candidate (ADTS/MP3/Annex B), on the principle that ES
frames inside a container payload are expected data, not evidence the file
is a raw stream.
§Insufficient vs Unknown
These are deliberately distinct, and a caller must not conflate them:
Probe::Insufficient { need_at_least }means read more bytes — nothing conclusive matched yet, but a longer buffer could change that. Useneed_at_leastto decide how much more to buffer.Probe::Unknownmeans stop — nothing matched and more bytes will not help.
§The loop that terminates
need_at_least is guaranteed to exceed the number of bytes the probe
actually examined, which is min(len, budget) — not len. So a caller
that only grows the buffer, while leaving probe’s fixed
DEFAULT_BUDGET in place, can stall once the budget caps the read. Feed
need_at_least back as the budget too:
let mut buf = read_at_least(DEFAULT_BUDGET);
let verdict = loop {
match probe_with_budget(&buf, buf.len()) {
Probe::Insufficient { need_at_least, .. } if need_at_least > buf.len() => {
let grown = read_at_least(need_at_least);
// EOF with nothing conclusive: stop. The probe cannot answer
// from this file, and no further read will change that.
if grown.len() <= buf.len() {
break Probe::Unknown;
}
buf = grown;
}
other => break other,
}
};Passing buf.len() as the budget is what makes each turn examine ground the
last one did not. The grown.len() <= buf.len() arm is the caller’s own
termination guarantee at EOF, and is not optional: the crate cannot know
whether more bytes exist.
§no_std + alloc
The crate is #![no_std] and links only alloc. Its single runtime
dependency is broadcast-common. The only allocation is the candidate Vec
of a genuine Ambiguous result. Build it without the default features for a
pure-alloc target.
§Example
use container_probe::{probe, Probe};
// An empty slice is `Insufficient`: reading more bytes could make it any
// registered format, so a caller must not stop — it must read more. This is
// the honest contract for a buffer that has not yet ruled anything out.
let p = probe(&[]);
match p {
Probe::Insufficient { need_at_least, .. } => assert!(need_at_least >= 1),
_ => unreachable!("an empty slice cannot be concluded from"),
}§Non-goals
- No demuxing — the probe identifies a format; parsing its content is a demuxer’s job.
- No codec identification — “this is TS” is the answer, not “this TS carries H.264”.
- No file IO —
no_std; the caller supplies bytes. - No format conversion or repair — identification only.
- No incremental/streaming API — the probe is one-shot over a slice; a
streaming caller reads more and re-probes, guided by
Insufficient’sneed_at_least.
no_std + alloc; runtime dependency is broadcast-common only.
Structs§
- Candidate
- One scored candidate: a format, the evidence strength behind it, and what the prober learned on the way.
- Confidence
- Evidence strength behind a match, in named tiers (see the
TIER_*constants and the crate-root confidence model).
Enums§
- Detail
- What a prober learned on the way to its conclusion — the difference between “it is TS” and “it is TS, 192-byte stride, first sync at offset 4”.
- DocType
- The EBML
DocTypestring ("webm"or"matroska") decoded from an EBML header’sEBMLDocTypeelement. - Format
- The identified container/stream format.
- Isobmff
Layout - How an ISOBMFF file carries its sample metadata — the discriminator a consumer needs to choose a demuxer.
- Partition
Kind - MXF Partition Pack kind — the
PartitionKindbyte, byte 14 of the Partition Pack Key UL (SMPTE ST 377-1 §7.2-7.4). - Probe
- What the probe concluded.
Constants§
- DEFAULT_
BUDGET - Default byte budget for
probe— comfortably above the worst case (a 208-byte-stride TS lattice needing 8 confirmations plus a full phase search). Design §Performance.
Functions§
- probe
- Probe with the default budget (
DEFAULT_BUDGET). - probe_
with_ budget - Probe reading at most
budgetbytes ofdata.