open-standards/wai/extensions/format-probes.md
2026-10-22 10:43:34 -04:00

510 lines
34 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WAI Extension: Format Probes
> Status: Draft. A **header probe** for each sink-supplied format the registry names whose
> payload WAI does not decode itself: it identifies a payload as the format its capability
> names and reads the parameters the format's headers state, or refuses it with one of the
> codes of §12. No probe decodes a picture or a sound. Probes are defined for JPEG XS
> (`wai.image.jxs`, `wai.video.jxs`), H.265 and MV-HEVC (`wai.video.hevc`,
> `wai.video.mvhevc`), H.266 (`wai.video.vvc`), LCEVC (`wai.video.lcevc`), MPEG-H 3D Audio
> (`wai.audio.mpegh`), AVS3 video and audio (`wai.video.avs3`, `wai.audio.avs3`), the picture
> header of IEEE 1857.11 (`wai.image.ieee1857_11`, a candidate) and the projection descriptor
> (`wai.meta.projection`, [projection](projection.md)). §3.5 maps a JPEG XS payload onto the
> media-type parameters of RFC 9134 and the constant-rate carriage of SMPTE ST 2110-22. The
> reference implementation is the `format_probe` module of `wai-rs` (feature
> `format_probe`) and its tool `wai_format_probe`; the corpus is
> [`format-probe-conformance/`](../format-probe-conformance/), and its second implementation
> is `format-probe-conformance/format_probe_verify.py`.
> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
>
> Texts read for this revision: ITU-T H.265 (V11, 01/2026) and ITU-T H.266 (V4, 01/2026),
> whole; ITU-T H.273 and ITU-T H.274 (V4, 01/2026) §8.15; RFC 9134; SMPTE ST 2110-22:2022; the
> public previews of ISO/IEC 21122-2:2022/Amd 1:2022 (Tables A.7 and A.16) and ISO/IEC
> 21122-4:2022 (§6.3, Annex B.2); ATSC A/342-3:2024-04 §5.2; ETSI TS 101 154 V2.10.1 §5.16.2 and
> §6.10.2. Not openly readable, and so not read: ISO/IEC 21122-1, ISO/IEC 23094-2, ISO/IEC
> 23008-3, T/AI 109.2, T/AI 109.3 and IEEE 1857.11-2024. For those formats §3 to §10 say where
> each layout was read instead.
## 1. Scope
§1.1 A probe reads a payload's headers. It identifies the format by the bytes the format
begins with, where it has such bytes (§2.4), reads the parameters its headers state, and checks
the structure the probe reads: the order of the format's required structures, the lengths they
declare, and the values the format forbids or reserves among the fields read. It reads no
coded sample data: a payload a probe accepts is not shown to decode, and a probe that accepts a
payload says nothing of the pictures or sounds in it.
§1.2 What a probe gives is used to describe a payload without decoding it: in a catalogue, in a
manifest a packager writes, in the `codecs` string or media-type parameters a delivery binding
states (§3.5), and to refuse a payload that does not hold the format its capability names before
any decoder sees it.
§1.3 An encoder **MUST NOT** emit, under a capability whose probe has basis `standard` or `wai`
(§2.3), a payload that probe refuses; it **SHOULD NOT** emit one that a probe of basis
`implementation` refuses. A sink **MAY** probe a payload before it dispatches it (SPEC §4); a
sink that probes and gets a refusal does not dispatch the payload under that capability, and
may still take dispatch step 5 with a fallback. A probe's refusal is not a statement that the
payload does not conform to its format's standard: a probe of basis `implementation` reads the
layout its sources give, and §12's `outside_probe` names payloads it cannot read at all.
§1.4 This extension adds no capability. It completes the registrations of `wai.video.vvc`,
`wai.video.lcevc`, `wai.audio.mpegh`, `wai.video.avs3` and `wai.audio.avs3`, which were
registered with no probe, and gives the registrations of `wai.image.jxs`, `wai.video.jxs`,
`wai.video.mvhevc`, `wai.image.ieee1857_11` and `wai.meta.projection` (SPEC §5) theirs.
## 2. Common rules
§2.1 A probe's result is a JSON object whose members each section names; a member the payload
does not state is `null`. Integers are JSON numbers, flags JSON booleans. The probe reports the
first refusal its reading meets, in the order each section reads.
§2.2 A bit reader reads most significant bit first. `u(n)` is an `n`-bit unsigned integer;
`ue(v)` is the Exp-Golomb code of ITU-T H.265 §9.2, and one with more than 31 leading zero bits
is `reserved_value`. Reading past the payload's end is `truncated`.
§2.3 Every probe has a **basis**: `standard`, where its format's own text is openly readable and
was read; `implementation`, where it is not and the layout was read from open implementations,
each section naming which agree; `wai`, for a format this specification defines.
§2.4 The probes, in order:
| capability | basis | section |
|---|---|---|
| `wai.image.jxs` | implementation | §3 |
| `wai.video.jxs` | implementation | §3.3 |
| `wai.video.hevc` | standard | §4 |
| `wai.video.mvhevc` | standard | §4 |
| `wai.video.vvc` | standard | §5 |
| `wai.video.lcevc` | implementation | §6 |
| `wai.audio.mpegh` | implementation | §7 |
| `wai.video.avs3` | implementation | §8 |
| `wai.audio.avs3` | implementation | §9 |
| `wai.image.ieee1857_11` | implementation | §10 |
| `wai.meta.projection` | wai | §11 |
Any other capability has no probe: `no_probe`.
§2.5 **Annex B byte streams.** A payload of H.265, H.266 or LCEVC is a byte stream: after any
zero bytes, it begins with the start code prefix `0x000001`, and otherwise is `no_signature`
(one zero byte before the prefix is not enough: at least two). A NAL unit is the bytes after a
prefix up to the next prefix, less the zero bytes that end it. Its payload is read with every
emulation-prevention byte removed: the `0x03` of every `0x000003` (ITU-T H.265 §7.4.2).
## 3. JPEG XS
§3.1 **Sources.** ISO/IEC 21122-1 is not openly readable. The marker codes, the segment
layouts and the order of §3.2 are those two independent open implementations of the codestream
agree on, a decoder and encoder under BSD-2-Clause-Patent and a decoder under MIT, at the
revisions `format-probe-conformance/tools/make_external.sh` pins. The profile codes are ISO/IEC
21122-2:2022/Amd 1:2022 Table A.7, and the sublevel codes its Table A.16, read in the
amendment's public preview. Level codes are named only where the two open readings agree
(§3.4).
§3.2 **The codestream.** A `wai.image.jxs` payload is one codestream. A probe reads, in order:
1. `SOC`, `0xFF10`, as the first two bytes; otherwise `no_signature`.
2. `CAP`, `0xFF50`, immediately after, and otherwise `out_of_order`; its length `Lcap`, a
big-endian `u16` of at least 2 (else `length_mismatch`), counts itself and `Lcap − 2` bytes of
capability bits, read most significant bit first: bit `i` set is reported in `cap_bits`.
3. `PIH`, `0xFF12`, immediately after `CAP`, else `out_of_order`, with `Lpih` 26, else
`length_mismatch`. Its body, big-endian: `Lcod` 32 bits, `Ppih` 16, `Plev` 16, `Wf` 16, `Hf`
16, `Cw` 16, `Hsl` 16, `Nc` 8, `Ng` 8, `Ss` 8, `Bw` 8, `Fq` 4, `Br` 4, `Fslc` 1, `Ppoc` 3,
`Cpih` 4, `Nlx` 4, `Nly` 4, `Lh` 1, `Rl` 1, `Qpih` 2, `Fs` 2, `Rm` 2. It is `reserved_value`
unless `Wf`, `Hf` and `Hsl` are at least 1, `Nc` is 1 to 8, `Ng` is 4, `Ss` is 8, `Br` is 4,
`Cpih` is 0, 1 or 3, and `Qpih` is 0 or 1.
4. Segments up to the first slice header `SLH`, `0xFF20`, each a marker, a big-endian `u16`
length of at least 2 (else `length_mismatch`) and that many bytes less two: `CDT` `0xFF13`,
`WGT` `0xFF14`, `COM` `0xFF15`, `NLT` `0xFF16`, `CWD` `0xFF17`, `CTS` `0xFF18`, `CRG`
`0xFF19`, in any order. `CDT`'s length is `2 + 2·Nc`, else `length_mismatch`; it holds, per
component, its precision `B` (8 bits) and its sampling factors `Sx` and `Sy` (4 bits each),
none of which is 0 (else `reserved_value`). `SOC`, `EOC`, `PIH` or `CAP` among these segments is
`out_of_order`; any other marker is `reserved_value`.
5. `CDT` and `WGT` are required before `SLH`, and with `Cpih` 3 also `CTS` and `CRG`:
`missing_structure`. The payload ends with `EOC`, `0xFF11`: otherwise `missing_structure`.
6. `Lcod` is 0 (a variable-rate codestream) or the codestream's length in bytes, `SOC` to `EOC`;
otherwise `length_mismatch`.
The probe does not read the slices.
§3.3 **Video.** A `wai.video.jxs` payload is five `u32` little-endian values, `n`, `h`, `w`,
`fps_num` and `fps_den`, then `n` codestreams, each preceded by its length as a `u32`
little-endian value: the framing of `wai.video.av1` (SPEC §5), with a codestream for a temporal
unit. Any of the five being 0 is `framing_invalid`; a length past the payload's end is
`truncated`; each codestream is probed by §3.2, and one whose `Wf` exceeds `w` or whose `Hf`
exceeds `h` is `framing_invalid`; bytes after the `n`-th codestream are `trailing_bytes`.
§3.4 **Parameters.** For one codestream: `profile` and `level` (`Ppih` and `Plev` as four
lowercase hexadecimal digits after `0x`), `width` and `height` (`Wf`, `Hf`), `components` (per
component `[B, Sx, Sy]`), `structure`, `colour_transform` (`Cpih`), `decompositions`
(`[Nlx, Nly]`), `precinct_width` (`Cw`), `slice_height` (`Hsl`), `wavelet_precision` (`Bw`),
`fractional_bits` (`Fq`), `quantizer` (`Qpih`), `long_header` (`Lh`), `raw_mode` (`Rl`),
`cbr_bytes` (`Lcod`), `cap_bits`, and `rtp` (§3.5). `structure` is `"4:4:4"`, `"4:2:2"` or
`"4:2:0"` when there are at least three components, the first has `Sx` = `Sy` = 1 and the second
and third have equal factors of (1, 1), (2, 1) or (2, 2) respectively; otherwise `null`.
For a video: `frames` (`n`), `size` (`[w, h]`), `fps` (`[fps_num, fps_den]`),
`constant_bytes` (the common `Lcod` when every codestream states the same non-zero `Lcod`,
otherwise `null`) and `first`, the first codestream's parameters.
The profile names (white space omitted, as RFC 9134 §7.1 writes them), by `Ppih`:
| `Ppih` | profile | `Ppih` | profile |
|---|---|---|---|
| `0x0000` | Unrestricted | `0x4240` | High420.12 |
| `0x1500` | Light422.10 | `0x4A40` | High444.12 |
| `0x1A00` | Light444.12 | `0x4E40` | High4444.12 |
| `0x2500` | Light-Subline422.10 | `0x6EC0` | MLS.12 |
| `0x3240` | Main420.12 | `0x9300` | LightBayer |
| `0x3540` | Main422.10 | `0xB340` | MainBayer |
| `0x3A40` | Main444.12 | `0xC340` | HighBayer |
| `0x3E40` | Main4444.12 | | |
The level, by `Plev`'s high byte: `0x00` Unrestricted, `0x10` 2k-1, `0x20` 4k-1, `0x24` 4k-2,
`0x28` 4k-3, `0x30` 8k-1, `0x34` 8k-2, `0x38` 8k-3, `0x40` 10k-1. The high bytes `0x04` and
`0x2C` are named 1k-1 and 5k-1 by one open implementation and refused as reserved by the other;
the probe names them too, and §3.6 records the disagreement. The sublevel, by `Plev`'s low byte:
`0x00` Unrestricted, `0x80` Full, `0x10` Sublev12bpp, `0x0C` Sublev9bpp, `0x08` Sublev6bpp,
`0x06` Sublev4bpp, `0x04` Sublev3bpp, `0x03` Sublev2bpp. A code in none of these lists is
reported with a `null` name and is not refused: a later edition may define it.
§3.5 **RTP and SMPTE ST 2110-22.** RFC 9134 carries a JPEG XS codestream in RTP; SMPTE ST
2110-22:2022 carries constant-bit-rate compressed video over RTP and names no codec. A sender of
a `wai.video.jxs` payload over RFC 9134:
- states the media type `video/jxsv` with the parameters of `rtp` (RFC 9134 §7.1): `profile`,
`level` and `sublevel` by the names of §3.4 (omitted where `null`), `depth` (the largest
component precision), `width` and `height`, and `sampling` where the codestream determines it:
`RGB` where `structure` is `4:4:4` under a colour transform (`Cpih` 1 or 3), whose decoder
outputs R, G and B; otherwise `rtp.sampling` is `null` and the sender states the sampling,
since a codestream does not say whether its components are Y′C′BC′R, constant-luminance
Y′C′BC′R or ICTCP (RFC 9134 §7.1 lists all three);
- sends each codestream as one picture segment of codestream mode (`K` = 0, RFC 9134 §4.1) at
the frame rate `fps`, the RTP timestamp at 90 kHz (RFC 9134 §4.2), or each slice in slice mode
(`K` = 1);
- for SMPTE ST 2110-22 (§4 there: a constant number of bytes, and of RTP packets, per frame),
sends only a payload whose `constant_bytes` is not `null`; the codestream's `Lcod` is the
frame's byte count.
A receiver rebuilds the payload by framing each received codestream as §3.3 does, `fps` from
the session's `exactframerate`. WAI defines no transport (moq-streaming-format §6); this
mapping says which of a payload's fields fill which of RFC 9134's.
§3.6 **Exactness.** A sink that advertises `wai.image.jxs` or `wai.video.jxs` decodes at the
strict conformance point of ISO/IEC 21122-4 (Annex B.2: decoded images bitwise identical to the
reference images), not only at its relaxed point (PSNR bounds), so every conforming sink outputs
the same samples; the registry class is `standard-defined` on that basis. What was measured
(`format-probe-conformance/provenance.json`): the open decoder's C path and SIMD path give
byte-identical output on every JPEG XS vector of the corpus, on arm64; the second, independent
decoder gives the same bytes on every vector whose profile it implements, five of six; it does
not implement MLS.12 (it refuses `Ppih` `0x6EC0`), and on a copy of that vector with `Ppih` and
`Plev` set to 0 its output differs, while the first decoder's output equals the vector's source
picture byte for byte, as a lossless codestream's must. No x86 decode was measured.
## 4. H.265 and MV-HEVC
§4.1 **Sources.** ITU-T H.265 (V11, 01/2026): the NAL unit header (§7.3.1.2), the video
parameter set and its extension (§F.7.3.2.1, §F.7.3.2.1.1, derivations (F-2) to (F-6)), the
sequence parameter set (§7.3.2.2.1), profile_tier_level (§7.3.3, inference §F.7.4.4) and the HRD
parameters (§E.2.2, §E.2.3).
§4.2 **NAL units.** Each NAL unit (§2.5) is at least 2 bytes (else `truncated`); its header is
`forbidden_zero_bit` 1, `nal_unit_type` 6, `nuh_layer_id` 6, `nuh_temporal_id_plus1` 3 bits.
`forbidden_zero_bit` 1 or `nuh_temporal_id_plus1` 0 is `reserved_value`. Types 0 to 31 are VCL.
The probe reads the first VPS (type 32) and the first SPS (type 33) with `nuh_layer_id` 0. A VCL
NAL unit before both is `out_of_order` if both occur later in the payload and `missing_structure`
if either never does; a payload with no VCL NAL unit is `missing_structure`.
§4.3 **The VPS.** In order: `vps_video_parameter_set_id` u(4), `vps_base_layer_internal_flag`,
`vps_base_layer_available_flag`, `vps_max_layers_minus1` u(6), `vps_max_sub_layers_minus1` u(3)
(above 6 is `reserved_value`), `vps_temporal_id_nesting_flag`, `vps_reserved_0xffff_16bits` (any
other value is `reserved_value`), profile_tier_level(1, `vps_max_sub_layers_minus1`), the
sub-layer ordering information, `vps_max_layer_id` u(6), `vps_num_layer_sets_minus1` ue(v)
(above 1023 is `reserved_value`), the layer-id flags, the timing information with its HRD
parameters (`vps_num_hrd_parameters` above `vps_num_layer_sets_minus1` + 1 is `reserved_value`;
`cpb_cnt_minus1` above 31 is `reserved_value`), and `vps_extension_flag`. When the flag is 1 and
`vps_max_layers_minus1` is above 0, the probe reads the alignment bits (each 1, else
`reserved_value`) and `vps_extension( )` up to and including its profile_tier_level( )
structures: `splitting_flag`, the sixteen `scalability_mask_flag`s, the dimension lengths, the
layer ids (each above the one before, else `reserved_value`), the dimension ids, `view_id_len`
and the view ids, the direct dependency flags, `num_add_layer_sets` and its
`highest_layer_idx_plus1` fields, the sub-layer and inter-layer temporal fields,
`default_ref_layers_active_flag`, `vps_num_profile_tier_level_minus1` (above 63 is
`reserved_value`) and the structures it counts. A profile_tier_level( ) is read as §7.3.3 lays it
out, its general profile part as 88 bits whatever its branches (the syntax's own note). A
structure with no profile takes its profile, tier and compatibility flags from the structure
before it (§F.7.4.4).
§4.4 **The SPS** of the base layer: `sps_video_parameter_set_id` u(4), `sps_max_sub_layers_minus1`
u(3) (above 6 is `reserved_value`), `sps_temporal_id_nesting_flag`, profile_tier_level(1, ·),
`sps_seq_parameter_set_id` ue(v) (above 15 is `reserved_value`), `chroma_format_idc` ue(v) (above
3 is `reserved_value`), `separate_colour_plane_flag` when it is 3, `pic_width_in_luma_samples`
and `pic_height_in_luma_samples` ue(v) (0 is `reserved_value`), the conformance window, and
`bit_depth_luma_minus8` and `bit_depth_chroma_minus8` ue(v) (above 8 is `reserved_value`). The
cropped size is the coded size less the window, whose offsets count SubWidthC and SubHeightC
samples (2 and 2 at 4:2:0, 2 and 1 at 4:2:2, 1 and 1 otherwise); a window as large as the
picture is `reserved_value`.
§4.5 **MV-HEVC.** A `wai.video.mvhevc` payload is also refused `not_multiview` unless the VPS
extension's scalability mask has bit 1 (multiview, Table F.1), `NumViews` (F-3) is at least 2, and
a VCL NAL unit with `nuh_layer_id` above 0 is present.
§4.6 **Parameters.** `profile_idc`, `tier`, `level_idc` (the base SPS's), `chroma_format_idc`,
`bit_depth` (`[luma, chroma]`), `coded` and `cropped` (`[width, height]`), `layers`
(`Min(62, vps_max_layers_minus1)` + 1), `layers_present` (the `nuh_layer_id`s of the VCL NAL units,
ascending), and, when the VPS extension was read, `multilayer`: `scalability_mask` (bit `i` for
`scalability_mask_flag[ i ]`), `layer_ids`, `view_order` and `aux` (`ViewOrderIdx` and `AuxId` per
layer), `views` (`NumViews` when the multiview bit is set, else 1), `view_ids` (`view_id_val`, or
zeros when `view_id_len` is 0), `profiles` (`general_profile_idc` of each extension structure,
after inference) and `multiview_profile` (whether any of them indicates profile 6, Multiview Main
or Multiview Main 10, by its idc or its compatibility flag).
## 5. H.266
§5.1 **Sources.** ITU-T H.266 (V4, 01/2026) §7.3.1.2, §7.3.2.3, §7.3.2.4, §7.3.3.1 and §7.3.3.2.
§5.2 **NAL units.** The header is `forbidden_zero_bit` 1, `nuh_reserved_zero_bit` 1,
`nuh_layer_id` 6, `nal_unit_type` 5, `nuh_temporal_id_plus1` 3 bits. Either of the first two set,
`nuh_temporal_id_plus1` 0 or `nuh_layer_id` above 55 is `reserved_value`. Types 0 to 11 are VCL.
The probe reads the first SPS (type 15) and the first VPS (type 14), of which it reads
`vps_max_layers_minus1` (the second field, after a 4-bit id). A VCL NAL unit before the SPS is
`out_of_order` if an SPS occurs later and `missing_structure` if none does; no VCL NAL unit is
`missing_structure`.
§5.3 **The SPS** to its conformance window: `sps_seq_parameter_set_id` u(4),
`sps_video_parameter_set_id` u(4), `sps_max_sublayers_minus1` u(3) (above 6 is `reserved_value`),
`sps_chroma_format_idc` u(2), `sps_log2_ctu_size_minus5` u(2) (above 2 is `reserved_value`),
`sps_ptl_dpb_hrd_params_present_flag` and, when it is 1, profile_tier_level(1,
`sps_max_sublayers_minus1`), `sps_gdr_enabled_flag`, `sps_ref_pic_resampling_enabled_flag` and
the flag it conditions, `sps_pic_width_max_in_luma_samples` and
`sps_pic_height_max_in_luma_samples` ue(v) (0 is `reserved_value`), and the conformance window.
profile_tier_level( ) is read as §7.3.3.1 lays it out; general_constraints_info( ) is
`gci_present_flag`, then, when it is 1, 71 bits of constraints, `gci_num_additional_bits` u(8)
and that many bits, then zero bits to the byte boundary (a one among them is `reserved_value`).
The cropped size is computed as in §4.4.
§5.4 **Parameters.** `profile_idc`, `tier`, `level_idc`, `frame_only`
(`ptl_frame_only_constraint_flag`) and `multilayer_enabled` (`ptl_multilayer_enabled_flag`), all
`null` when the SPS carries no profile_tier_level( ); `sub_profiles` (`general_sub_profile_idc`s);
`chroma_format_idc`; `ctu_size` (`1 << (sps_log2_ctu_size_minus5 + 5)`); `coded`; `cropped`;
`layers` (`vps_max_layers_minus1` + 1, or 1 without a VPS); `layers_present`.
## 6. LCEVC
§6.1 **Sources.** ISO/IEC 23094-2 is not openly readable. The NAL unit header, the block
structure and the two configurations are those an open decoder (BSD-3-Clause-Clear) and an open
syntax reading under LGPL-2.1 agree on, each citing the standard's tables; the resolution table
is the standard's Table 20 as the decoder reproduces it. The two readings disagree on the byte
that extends a profile or level of 15; the probe does not read it (`outside_probe`).
§6.2 **NAL units.** A `wai.video.lcevc` payload is the byte stream of SPEC §5 (§2.5). Each NAL
unit is at least 3 bytes (else `truncated`). Its first byte is `forbidden_zero_bit` (0),
`forbidden_one_bit` (1), `nal_unit_type` (5 bits) and the first bit of `reserved_flag` (1); its
second byte is the other eight bits of `reserved_flag`, all 1. Any other value of those bits is
`reserved_value`. `nal_unit_type` is 29 (IDR) or 28 (non-IDR), else `reserved_value`; the first NAL
unit is IDR, else `out_of_order`. The payload, emulation prevention removed, ends with the byte
`0x80`, else `reserved_value`.
§6.3 **Blocks.** The payload before that byte is a sequence of blocks: a header byte, its high
three bits `payload_size_type` and its low five `payload_type`, then the body. A size type of 0 to
5 is the body's length; 6 is `reserved_value`; 7 is followed by the length as a multi-byte value:
seven bits a byte, most significant first, each byte but the last with its top bit set, at most
ten bytes (else `reserved_value`). A body past the payload's end is `length_mismatch`. Types: 0
sequence configuration, 1 global configuration, 2 picture configuration, 3 and 4 encoded data,
5 additional information, 6 filler; the probe reads the first 0 and the first 1, counts the 2s,
and passes over the rest. A picture configuration before both configurations is `out_of_order`;
a payload without both is `missing_structure`.
§6.4 **The configurations.** The sequence configuration: `profile_idc` 4, `level_idc` 4,
`sublevel_idc` 2, `conformance_window_flag` 1, five reserved bits that are 0 (else
`reserved_value`); a profile or level of 15 is `outside_probe`; with the flag, four multi-byte
window offsets (left, right, top, bottom); bytes left in the body are `length_mismatch`. The
global configuration: `processed_planes_type_flag` 1, `resolution_type` 6, `transform_type` 1,
`chroma_sampling_type` 2, `base_depth_type` 2, `enhancement_depth_type` 2,
`temporal_step_width_modifier_signalled_flag` 1, `predicted_residual_mode_flag` 1,
`temporal_tile_intra_signalling_enabled_flag` 1, `temporal_enabled_flag` 1, `upsample_type` 3,
`level1_filtering_signalled_flag` 1, `scaling_mode_level1` 2, `scaling_mode_level2` 2,
`tile_dimensions_type` 2, `user_data_enabled` 2, `level1_depth_flag` 1, `chroma_step_width_flag`
1; then, each where its condition holds: a byte of planes type (the planes flag), a byte of step
width modifier (its flag), four 16-bit kernel coefficients (`upsample_type` 4), a byte of two
filter coefficients (the filtering flag), for `tile_dimensions_type` above 0 the custom tile
width and height as 16-bit values when it is 3 and then a byte of tile compression, and, for
`resolution_type` 63, the custom width and height as 16-bit values. `resolution_type` 0 or 51 to
62, an `upsample_type` above 4, or a custom width or height of 0 is `reserved_value`.
§6.5 **Parameters.** `nal_units` (`[IDR, non-IDR]` counts), `pictures` (picture configurations),
`profile_idc`, `level_idc`, `sublevel_idc`, `conformance_window` (the four offsets as signalled,
or `null`), `resolution_type`, `size` (Table 20's for types 1 to 50, the custom size for 63),
`transform_type`, `chroma_sampling_type`, `base_depth` and `enhancement_depth` (`8 + 2·type`),
`temporal_enabled`, `upsample_type`, `tile_dimensions_type`.
Table 20, types 1 to 50: 360×200, 400×240, 480×320, 640×360, 640×480, 768×480, 800×600,
852×480, 854×480, 856×480, 960×540, 960×640, 1024×576, 1024×600, 1024×768, 1152×864,
1280×720, 1280×800, 1280×1024, 1360×768, 1366×768, 1400×1050, 1440×900, 1600×1200, 1680×1050,
1920×1080, 1920×1200, 2048×1080, 2048×1152, 2048×1536, 2160×1440, 2560×1440, 2560×1600,
2560×2048, 3200×1800, 3200×2048, 3200×2400, 3440×1440, 3840×1600, 3840×2160, 3840×2400,
4096×2160, 4096×3072, 5120×2880, 5120×3200, 5120×4096, 6400×4096, 6400×4800, 7680×4320,
7680×4800.
## 7. MPEG-H 3D Audio
§7.1 **Sources.** ISO/IEC 23008-3 is not openly readable. The MHAS packet syntax, the packet
types and the first fields of the configuration are those two independent open decoders agree
on; the low-complexity profile-level codes 0x0B to 0x0D are confirmed by ATSC A/342-3:2024-04
§5.2.2.1. Neither open decoder is under a licence this corpus can use, so the corpus's MHAS
vectors are written by its generator (§13.2).
§7.2 **Packets.** A `wai.audio.mpegh` payload is an MHAS stream: packets, each a header of
`MHASPacketType` = escapedValue(3, 8, 8), `MHASPacketLabel` = escapedValue(2, 8, 32) and
`MHASPacketLength` = escapedValue(11, 24, 24), then that many bytes. escapedValue(n1, n2, n3)
reads `v` = u(n1); when `v` is 2^n1 − 1 it reads `a` = u(n2) and adds it; when `a` is
2^n2 − 1 it reads u(n3) and adds that too. Every header is a whole number of bytes. The first
packet is a synchronisation packet (type 6) or a configuration packet (type 1), else
`no_signature`; a packet past the end is `truncated`. A synchronisation packet has label 0 and the
one byte `0xA5`, else `reserved_value`. A frame packet (type 2) before the first configuration is
`out_of_order`; a payload with no configuration is `missing_structure`. Other types are passed
over.
§7.3 **The configuration.** The first configuration packet's payload: the profile-level
indication u(8); `usacSamplingFrequencyIndex` u(5), its rate by the table below, or, for 31, a
rate u(24) (0 is `reserved_value`); `coreSbrFrameLengthIndex` u(3); one reserved bit;
`receiverDelayCompensation` u(1); `speakerLayoutType` u(2); then, for type 0,
`CICPspeakerLayoutIdx` u(6), and for types 1 and 2 the speaker count, escapedValue(5, 8, 16) + 1.
Rates by index 0 to 30: 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000,
11025, 8000, 7350, reserved, reserved, 57600, 51200, 40000, 38400, 34150, 28800, 25600, 20000,
19200, 17075, 14400, 12800, 9600, reserved, reserved, reserved; a reserved index is
`reserved_value`.
§7.4 **Parameters.** `profile_level`; `profile` and `level`: `low-complexity` 1 to 5 for 0x0B to
0x0F, `baseline` 1 to 5 for 0x10 to 0x14, else `null`; `sampling_rate`; `core_frame_length_index`;
`speaker_layout_type`; `cicp_layout`; `speakers`; and the counts `packets`, `frames`, `syncs` and
`configs`.
## 8. AVS3 video
§8.1 **Sources.** T/AI 109.2 is not openly readable. The sequence header and the pseudo-start-code
prevention are read as an open decoder (BSD-3-Clause) reads them, with the start codes it and an
open syntax reading under LGPL-2.1 agree on. ETSI TS 101 154 V2.10.1 §5.16.2 requires the library
flags to be 0 and confirms the profile codes 0x20, 0x22 and 0x32.
§8.2 **Units.** A `wai.video.avs3` payload begins, after any zero bytes (at least two), with the
prefix `0x000001`, else `no_signature`. A unit is the byte after a prefix (its start code) and the
bytes up to the next prefix. A unit's bytes are read with the prevention bits removed: in each
byte `0x02` that follows two zero bytes of the unit, its two low bits. Start codes: `0xB0`
sequence header, `0xB1` sequence end, `0xB3` intra picture, `0xB6` inter picture. A payload with no
sequence header is `missing_structure`; one whose first unit is not one is `out_of_order`; one
with no intra picture is `missing_structure`.
§8.3 **The sequence header.** `profile_id` u(8), `level_id` u(8), `progressive_sequence` u(1),
`field_coded_sequence` u(1), `library_stream_flag` u(1) (1 is `outside_probe`),
`library_picture_enable_flag` u(1) (1 is `outside_probe`: a flag follows whose place the open
texts do not establish), `marker_bit`, `horizontal_size` u(14), `marker_bit`, `vertical_size` u(14),
`chroma_format` u(2), `sample_precision` u(3), `encoding_precision` u(3) for profiles 0x22 and
0x32 only, `marker_bit`, `aspect_ratio` u(4), `frame_rate_code` u(4), `marker_bit`,
`bit_rate_lower` u(18), `marker_bit`, `bit_rate_upper` u(12), `low_delay` u(1),
`temporal_id_enable_flag` u(1), `marker_bit`, `bbv_buffer_size` u(18), `marker_bit`,
`max_dpb_size_minus1` u(4). A `marker_bit` of 0 is `reserved_value`, and so are a size, chroma
format or sample precision of 0 and a frame rate code of 0 or above 13.
§8.4 **Parameters.** `profile_id`, `level_id`, `progressive`, `field_coded`, `size`,
`chroma_format`, `sample_precision`, `encoding_precision` (or `null`), `aspect_ratio`,
`frame_rate_code`, `bit_rate` (`bit_rate_upper` · 2^18 + `bit_rate_lower`), `low_delay`,
`temporal_id_enabled`, `bbv_buffer_size`, `max_dpb_size`, `pictures` (`[intra, inter]` counts) and
`sequence_end` (whether a sequence end unit is present).
## 9. AVS3 audio
§9.1 **Sources.** T/AI 109.3 is not openly readable. The frame header is read as an open
demultiplexer under LGPL-2.1 reads it; ETSI TS 101 154 V2.10.1 §6.10.2 constrains the values a
broadcast stream uses. The demultiplexer reads only the lossy codec and refuses ancillary data,
and the probe does the same (`outside_probe`). It also skips two 8-bit fields it does not name,
and so does the probe. The header states no frame length, so the probe reads the first frame's
header only.
§9.2 **The header.** A sync word of 12 bits, `0xFFF` (else `no_signature`); `audio_codec_id` u(4)
(1, lossless, is `outside_probe`; anything but 2 is `reserved_value`); `anc_data` u(1) (1 is
`outside_probe`); `nn_type` u(3) (above 1 is `reserved_value`); `coding_profile` u(3) (above 2 is
`reserved_value`); `sampling_frequency_index` u(4), rates 192000, 96000, 48000, 44100, 32000,
24000, 22050, 16000, 8000 (above 8 is `reserved_value`); 8 bits; then for profile 0
`channel_number_index` u(7); for profile 1 `soundbed_type` u(2): for 0 the object count less one
u(7) and the per-object bitrate index u(4), for 1 `channel_number_index` u(7), the bitrate index
u(4), the object count less one u(7) and the per-object bitrate index u(4), and above 1
`reserved_value`; for profile 2 the ambisonic order less one u(4) (an order outside 1 to 3 is
`reserved_value`); then `resolution` u(2) (above 2 is `reserved_value`), the bitrate index u(4)
unless the profile is 1, and 8 bits.
§9.3 **Parameters.** `codec_id`, `nn_type`, `coding_profile`, `sampling_rate`, and as the profile
gives them `channel_number_index`, `soundbed_type`, `objects`, `bitrate_index`,
`bitrate_index_per_object`, `ambisonic_order`; and `resolution_bits` (8 · (`resolution` + 1)).
## 10. IEEE 1857.11
§10.1 `wai.image.ieee1857_11` is a candidate (SPEC §5): IEEE 1857.11-2024 is not openly readable,
and the open reference software (BSD-2-Clause) writes a picture header with no start code, from a
working draft, marking the code that would write one as not yet written. So no payload format is
pinned. This parse reads that header as the software's writer lays it out, at the revision the
corpus README names. Its reader masks `level_id` differently from its writer; the parse follows
the writer. With no signature, the parse cannot tell this format from another; it reads a payload
declared to be one, and never refuses `no_signature`.
§10.2 **The header**, big-endian: 3 bytes holding `profile_id` (3 bits), `level_id` (6),
`model_id` (3), `parameter_set_id` (7) and `quality_id` (5); the picture's height and width as
32-bit values; 2 bytes holding 2 unused bits (0), `output_bit_depth` (3), `picture_format` (3),
`log2_slice_size_h_minus6` (4) and `log2_slice_size_w_minus6` (4). Fewer than 13 bytes is
`truncated`. A `profile_id` above 2, an unused bit set, an `output_bit_depth` other than 1 (8
bits) or 2 (10 bits), or a height or width of 0 is `reserved_value`.
§10.3 **Parameters.** `profile_id`, `level_id`, `model_id`, `parameter_set_id`, `quality_id`,
`size` (`[width, height]`), `bit_depth`, `picture_format`, `slice_size`
(`[2^(w+6), 2^(h+6)]`).
## 11. The projection descriptor
§11.1 The probe of `wai.meta.projection` reads the descriptor as [projection](projection.md) §3
lays it out and checks it as its §4 does; its parameters are those of projection.md §3. The
check of a descriptor against the rendition it accompanies, which needs that rendition's probe,
is projection.md §5's.
## 12. Refusals
| code | meaning |
|---|---|
| `no_signature` | the payload does not begin with the format's signature |
| `truncated` | the bytes end inside a structure the probe reads |
| `out_of_order` | a structure is where the format does not allow it |
| `reserved_value` | a field holds a value the format forbids or reserves |
| `length_mismatch` | a length a structure declares disagrees with the bytes |
| `missing_structure` | a structure the format requires is absent |
| `not_multiview` | a `wai.video.mvhevc` payload with no second view |
| `framing_invalid` | the framing of a `wai.video.jxs` payload is wrong |
| `trailing_bytes` | bytes follow the end of the payload's last structure |
| `descriptor_invalid` | a projection descriptor's fields disagree with each other |
| `layer_absent` | a projection descriptor names a layer its rendition does not hold |
| `outside_probe` | the payload uses a feature whose syntax the probe's sources do not establish |
| `no_probe` | no probe is defined for the capability |
## 13. Conformance
§13.1 [`format-probe-conformance/`](../format-probe-conformance/) holds `vectors.json`: every
vector's capability, file, SHA-256, origin and outcome (its parameters, or its refusal), the
projection descriptors' bindings with theirs (projection.md §5), and the facts of §13.2.
§13.2 **External vectors** (`ext/`) were written by permissively licensed encoders at pinned
revisions from synthetic pictures, and each was decoded again; `tools/make_external.sh` writes
them and `provenance.json`, which records every command and decode. **Facts** are what each
encoder was asked for (a size, a profile, a view count): the probe must read them, which ties the
probe to the encoder and not to itself. **Generated vectors** (`gen/`) are written by
`wai_format_probe gen` from fixed values and from the external vectors: the formats no
permissively licensed encoder writes (LCEVC, MHAS, AVS3 audio, the IEEE 1857.11 header, the
projection descriptor) and the negative controls, each refused with a code of §12, every code
given.
§13.3 **Fetched vectors.** `fetch.sh` fetches five LCEVC streams an open decoder's tests use,
written by an LCEVC encoder, and checks each SHA-256; the corpus names them and does not hold
them, because their licence notice names their owner. Each is a container of blocks (an 8-byte
magic `lcevcbin`, a `u32` version, then per block a `u16` type, a `u32` size and that many bytes,
the first 16 of which are two indices) whose remaining bytes, concatenated, are the byte stream.
`vectors.json` states, for each, what its encoder was asked for.
§13.4 `wai_format_probe verify` and `wai-rs/tests/format_probe.rs` require every outcome, binding
and fact, and the generated files byte for byte; with `--fetched` the verifier requires every
fetched stream. `format_probe_verify.py`, written from this text and projection.md and sharing no
code with wai-rs, does the same, and requires every mutated copy of the corpus to fail.