Skip to main content

oxideav_av1/
lib.rs

1//! # oxideav-av1
2//!
3//! **Status:** orphan-rebuild scaffold (post 2026-05-20 audit), clean
4//! room rebuild in progress.
5//!
6//! The decoder/encoder pipeline is not wired up yet. Bitstream
7//! parsing has reached:
8//!
9//!   * **Round 1.** OBU bytestream walker described in §5.3 of the
10//!     AV1 Bitstream & Decoding Process Specification — boundaries
11//!     in a low-overhead bitstream plus `obu_type` /
12//!     `obu_extension_flag` / `obu_has_size_field` / `temporal_id` /
13//!     `spatial_id` / `obu_size` fields and a payload slice for each
14//!     unit. See [`obu`].
15//!
16//!   * **Round 2.** Sequence header OBU parse per §5.5
17//!     (`sequence_header_obu`, `color_config`, `timing_info`,
18//!     `decoder_model_info`, `operating_parameters_info`). Returns a
19//!     strongly typed [`sequence_header::SequenceHeader`] descriptor
20//!     plus a bit-position so the trailing-bits accounting from
21//!     §5.3.1 can plug in cleanly next round. See [`sequence_header`].
22//!
23//!   * **Round 3.** Leading slice of `uncompressed_header()` per
24//!     §5.9.2 — `show_existing_frame` / `frame_to_show_map_idx` /
25//!     `display_frame_id` / `frame_type` / `show_frame` /
26//!     `showable_frame` / `error_resilient_mode` /
27//!     `disable_cdf_update` / `allow_screen_content_tools` /
28//!     `force_integer_mv` / `current_frame_id` /
29//!     `frame_size_override_flag` / `order_hint` /
30//!     `primary_ref_frame` / `refresh_frame_flags`. Composes with
31//!     round-2's `SequenceHeader` to drive every conditional read.
32//!     See [`frame_header`].
33//!
34//!   * **Round 4.** Frame-size sub-syntax block per §5.9.5
35//!     (`frame_size`) + §5.9.6 (`render_size`) + §5.9.8
36//!     (`superres_params`) + §5.9.9 (`compute_image_size`). For
37//!     every intra (`KEY_FRAME` / `INTRA_ONLY_FRAME`) frame in the
38//!     §5.9.2 syntax tree, [`parse_frame_header`] now drops into
39//!     `frame_size()` + `render_size()` after `refresh_frame_flags`
40//!     and surfaces the eight-field [`FrameSize`] descriptor
41//!     (`frame_width` / `frame_height` / `render_width` /
42//!     `render_height` / `superres_denom` / `upscaled_width` /
43//!     `mi_cols` / `mi_rows`). The §5.9.7 `frame_size_with_refs()`
44//!     `found_ref` shortcut is **not** implemented yet — it reads
45//!     `RefUpscaledWidth[]` / `RefFrameHeight[]` /
46//!     `RefRenderWidth[]` / `RefRenderHeight[]` from a
47//!     reference-frame state table this round does not track —
48//!     so inter-frame parsing still stops at `refresh_frame_flags`
49//!     with `frame_size = None`. See [`frame_header`].
50//!
51//!   * **Round 6.** `allow_intrabc` (§5.9.3 path of §5.9.2) +
52//!     `tile_info()` (§5.9.15) wired into the streaming
53//!     [`parse_frame_header`] walk. For intra frames whose
54//!     `allow_screen_content_tools && UpscaledWidth == FrameWidth`
55//!     conjunction holds, the parser now consumes the `allow_intrabc`
56//!     `f(1)` slot — otherwise the spec's `allow_intrabc = 0`
57//!     initialiser stands. After the `frame_size()` / `render_size()`
58//!     block (intra path), the parser then walks `tile_info()` per
59//!     §5.9.15 and surfaces a typed [`tile_info::TileInfo`]
60//!     (`uniform_tile_spacing_flag`, `tile_cols`, `tile_rows`,
61//!     `tile_cols_log2`, `tile_rows_log2`, `context_update_tile_id`,
62//!     `tile_size_bytes`, `mi_col_starts`, `mi_row_starts`). The
63//!     non-uniform-spacing path consumes the `ns(maxWidth)` /
64//!     `ns(maxHeight)` `width_in_sbs_minus_1` / `height_in_sbs_minus_1`
65//!     fields via the new [`bitreader::BitReader::ns`] primitive
66//!     (§4.10.7). Tile-content decode (motion vectors, transform /
67//!     quantisation, in-loop filters, film grain) is still out of
68//!     scope. See [`tile_info`].
69//!
70//!   * **Round 5.** Uncompressed-header tail sub-syntaxes — §5.9.10
71//!     `read_interpolation_filter()` (returns
72//!     [`InterpolationFilter`]), §5.9.11 `loop_filter_params()`
73//!     (returns [`LoopFilterParams`] with the `CodedLossless ||
74//!     allow_intrabc` short-circuit, the four `loop_filter_level[]`
75//!     fields with the `NumPlanes > 1 && (level[0] || level[1])`
76//!     gate on the chroma slots, the `f(3)` `loop_filter_sharpness`,
77//!     and the `loop_filter_delta_enabled / delta_update /
78//!     update_ref_delta[i] / update_mode_delta[i]` per-slot
79//!     update walk over `TOTAL_REFS_PER_FRAME = 8` ref-deltas + 2
80//!     mode-deltas with `su(7)` signed offsets), and §5.9.12
81//!     `quantization_params()` + §5.9.13 `read_delta_q()` (returns
82//!     [`QuantizationParams`] with `base_q_idx`, the four
83//!     `delta_q_y_dc / delta_q_u_dc / delta_q_u_ac / delta_q_v_dc /
84//!     delta_q_v_ac` per-plane offsets, `diff_uv_delta` /
85//!     `using_qmatrix` / `qm_y` / `qm_u` / `qm_v`). These remain
86//!     available as standalone parser entry points
87//!     ([`parse_interpolation_filter`], [`parse_loop_filter_params`],
88//!     [`parse_quantization_params`]) for callers that want to
89//!     exercise the parsers on a raw byte slice. See
90//!     [`uncompressed_header_tail`].
91//!
92//!   * **Round 7.** §5.9.12 `quantization_params()` and §5.9.14
93//!     `segmentation_params()` wired into the streaming
94//!     [`parse_frame_header`] walk (intra path). After `tile_info()`
95//!     the parser now consumes `quantization_params()` and surfaces a
96//!     typed [`QuantizationParams`] on [`FrameHeader::quantization_params`],
97//!     then `segmentation_params()` and surfaces a typed
98//!     [`SegmentationParams`] on [`FrameHeader::segmentation_params`]
99//!     covering `segmentation_enabled`, `segmentation_update_map`,
100//!     `segmentation_temporal_update`, `segmentation_update_data`,
101//!     the full §5.9.14 `FeatureEnabled[i][j]` /
102//!     `FeatureData[i][j]` 8×8 table (`segment_feature_active` /
103//!     `segment_feature_data`), and the §5.9.14 trailing
104//!     `SegIdPreSkip` / `LastActiveSegId` derivations. The §5.9.14
105//!     `primary_ref_frame == PRIMARY_REF_NONE` collapse is honoured
106//!     (`update_map = 1`, `temporal_update = 0`, `update_data = 1`,
107//!     no bitstream reads for the three update flags). Per-feature
108//!     `Segmentation_Feature_Bits` / `Segmentation_Feature_Signed` /
109//!     `Segmentation_Feature_Max` Table 5.9.14 tables are exposed as
110//!     [`SEGMENTATION_FEATURE_BITS`] / [`SEGMENTATION_FEATURE_SIGNED`]
111//!     / [`SEGMENTATION_FEATURE_MAX`]. See
112//!     [`uncompressed_header_tail::parse_segmentation_params`].
113//!
114//!   * **Round 8.** §5.9.17 `delta_q_params()` and §5.9.18
115//!     `delta_lf_params()` wired into the streaming
116//!     [`parse_frame_header`] walk (intra path). After
117//!     `segmentation_params()` the parser consumes `delta_q_params()`
118//!     and surfaces a typed [`DeltaQParams`] on
119//!     [`FrameHeader::delta_q_params`] (`delta_q_present` — read as
120//!     `f(1)` only when `base_q_idx > 0`; `delta_q_res` — `f(2)`,
121//!     read only when `delta_q_present == 1`), then `delta_lf_params()`
122//!     and surfaces a typed [`DeltaLfParams`] on
123//!     [`FrameHeader::delta_lf_params`] (`delta_lf_present` — gated on
124//!     `delta_q_present` and suppressed when `allow_intrabc == 1`;
125//!     `delta_lf_res` / `delta_lf_multi` — read only when
126//!     `delta_lf_present == 1`). Both remain available as standalone
127//!     parser entry points
128//!     ([`uncompressed_header_tail::parse_delta_q_params`] /
129//!     [`uncompressed_header_tail::parse_delta_lf_params`]).
130//!   * **Round 9 — §5.9.11 `loop_filter_params()`** wired into the
131//!     streaming [`parse_frame_header`] walk (intra path). After
132//!     `delta_lf_params()` the parser derives `CodedLossless` from the
133//!     §5.9.2 lines that scan `LosslessArray[]` over the per-segment
134//!     qindexes (`get_qindex(1, segmentId)` with the §8.7 ignore-delta
135//!     branch and the `SEG_LVL_ALT_Q` `Clip3(0, 255, ..)` clamp), then
136//!     consumes `loop_filter_params()` and surfaces a typed
137//!     [`LoopFilterParams`] on [`FrameHeader::loop_filter_params`]. The
138//!     §5.9.11 `CodedLossless || allow_intrabc` short-circuit consumes
139//!     no bits and resets the ref-deltas to their §5.9.11 defaults; the
140//!     full path reads the four `loop_filter_level[]` slots (chroma pair
141//!     gated on `NumPlanes > 1 && (level[0] || level[1])`), the `f(3)`
142//!     `loop_filter_sharpness`, and the
143//!     `loop_filter_delta_enabled` / `delta_update` per-slot update walk.
144//!   * **Round 10 — §5.9.19 `cdef_params()`** wired into the streaming
145//!     [`parse_frame_header`] walk (intra path). After
146//!     `loop_filter_params()` the parser consumes `cdef_params()` and
147//!     surfaces a typed [`CdefParams`] on [`FrameHeader::cdef_params`].
148//!     The §5.9.19 `CodedLossless || allow_intrabc || !enable_cdef`
149//!     short-circuit consumes no bits and leaves `cdef_bits = 0`,
150//!     `CdefDamping = 3`, and all four strength arrays zeroed; the full
151//!     path reads `cdef_damping_minus_3` / `cdef_bits` and the
152//!     `1 << cdef_bits` `cdef_y_pri` / `cdef_y_sec` (+ `cdef_uv_*` when
153//!     `NumPlanes > 1`) strength entries, applying the secondary
154//!     `== 3 ⇒ += 1` adjustment. Also available as a standalone parser
155//!     entry point ([`parse_cdef_params`]).
156//!
157//!   * **Round 11 — §5.9.20 `lr_params()`** wired into the streaming
158//!     [`parse_frame_header`] walk (intra path). After `cdef_params()`
159//!     the parser consumes `lr_params()` and surfaces a typed
160//!     [`LrParams`] on [`FrameHeader::lr_params`]. The §5.9.20
161//!     `AllLossless || allow_intrabc || !enable_restoration`
162//!     short-circuit consumes no bits and leaves every plane
163//!     `RESTORE_NONE` with `UsesLr = 0`; the full path reads one
164//!     `lr_type` (`f(2)`) per plane (mapped through `Remap_Lr_Type` into
165//!     [`FrameRestorationType`]), then — when any plane uses LR —
166//!     `lr_unit_shift` (post-incremented for 128×128 superblocks,
167//!     otherwise extended by `lr_unit_extra_shift`) and the
168//!     4:2:0-chroma-gated `lr_uv_shift`, deriving the three
169//!     `LoopRestorationSize[]` entries from `RESTORATION_TILESIZE_MAX`.
170//!     Also available as a standalone parser entry point
171//!     ([`parse_lr_params`]).
172//!
173//!   * **Round 12 — §5.9.21 `read_tx_mode()`** wired into the streaming
174//!     [`parse_frame_header`] walk (intra path). After `lr_params()` the
175//!     parser consumes `read_tx_mode()` and surfaces a typed [`TxMode`]
176//!     on [`FrameHeader::tx_mode`]. When `CodedLossless == 1` the §5.9.21
177//!     first branch consumes no bits and forces [`TxMode::Only4x4`];
178//!     otherwise the `f(1)` `tx_mode_select` slot selects
179//!     [`TxMode::TxModeSelect`] (`1`) or [`TxMode::TxModeLargest`] (`0`).
180//!     Also available as a standalone parser entry point
181//!     ([`parse_tx_mode`]).
182//!
183//!   * **Round 13 — the §5.9.2 uncompressed-header tail** completes the
184//!     intra path. After `read_tx_mode()` the parser consumes
185//!     `frame_reference_mode()` (§5.9.23), `skip_mode_params()`
186//!     (§5.9.22), the `allow_warped_motion` slot, `reduced_tx_set`
187//!     (`f(1)`), `global_motion_params()` (§5.9.24), and
188//!     `film_grain_params()` (§5.9.30), surfacing
189//!     [`FrameHeader::reference_select`] / `skip_mode_present` /
190//!     `allow_warped_motion` / `reduced_tx_set` plus typed
191//!     [`GlobalMotionParams`] and [`FilmGrainParams`]. For an intra
192//!     frame the first three blocks and `global_motion_params()` all
193//!     collapse without reading bits (the §5.9.23 `FrameIsIntra ⇒
194//!     reference_select = 0`, the §5.9.22 `skipModeAllowed = 0`, the
195//!     §5.9.2 `allow_warped_motion` guard, and the §5.9.24 `FrameIsIntra`
196//!     identity short-circuit); `reduced_tx_set` is one bit, and
197//!     `film_grain_params()` reads its full §5.9.30 block when the
198//!     sequence enables grain and the frame carries `apply_grain == 1`.
199//!     `global_motion_params()` exposes the complete §5.9.24/§5.9.25
200//!     inter syntax (`read_global_param` + §5.9.26–§5.9.29
201//!     `decode_signed_subexp_with_ref` / `decode_subexp` /
202//!     `inverse_recenter`) via the standalone
203//!     [`parse_global_motion_params`]; `film_grain_params()` is likewise
204//!     available via [`parse_film_grain_params`] (taking a
205//!     [`FilmGrainContext`]). This is the end of `uncompressed_header()`
206//!     for the intra path — [`FrameHeader::bits_consumed`] now reaches
207//!     the trailing bits / tile-group boundary.
208//!
209//!   * **Round 14 — the inter-frame `uncompressed_header()` path.** An
210//!     `INTER_FRAME` / `SWITCH_FRAME` header now parses end-to-end. The
211//!     §5.9.2 `else` branch reads `frame_refs_short_signaling`, the
212//!     explicit `ref_frame_idx[]` (or computes them via §7.8
213//!     `set_frame_refs()`), the §5.9.7 `frame_size_with_refs()` /
214//!     §5.9.5 `frame_size()` + §5.9.6 `render_size()` size selection,
215//!     `allow_high_precision_mv`, §5.9.10 `read_interpolation_filter()`,
216//!     `is_motion_mode_switchable`, `use_ref_frame_mvs`, then the shared
217//!     `disable_frame_end_update_cdf` + `tile_info()` + quant / segment
218//!     / delta / loop-filter / CDEF / LR / `read_tx_mode()` tail, the
219//!     inter `frame_reference_mode()` (`reference_select`), §5.9.22
220//!     `skip_mode_params()`, `allow_warped_motion`, `reduced_tx_set`,
221//!     inter `global_motion_params()`, and `film_grain_params()`. Backed
222//!     by a new public [`frame_header::RefInfo`] cross-frame reference
223//!     state and surfaced via [`parse_frame_header_with_refs`] /
224//!     [`frame_header::InterFrameRefs`] (on
225//!     [`FrameHeader::inter_refs`]). Verified byte-exact against the
226//!     `i-frame-then-p-64x64` fixture's `idx=1` `FRAME_HEADER` +
227//!     `REF_MAP` trace lines.
228//!
229//!   * **Round 15.** The §8.2 symbol (arithmetic / msac) decoder, as a
230//!     standalone [`symbol_decoder::SymbolDecoder`]. Implements §8.2.2
231//!     `init_symbol` (the `SymbolValue` / `SymbolRange` / `SymbolMaxBits`
232//!     §8.2.4 state), §8.2.6 `read_symbol` (the CDF-adaptive multisymbol
233//!     search with `EC_PROB_SHIFT` / `EC_MIN_PROB`, the `prev - cur`
234//!     range update, and the seven-step renormalisation that draws new
235//!     bits — or §8.2.2 padding zeros once `SymbolMaxBits` is exhausted),
236//!     the §8.3 adaptive-rate CDF update, §8.2.3 `read_bool`, §8.2.5
237//!     `read_literal` (`L(n)`), `NS(n)` (§4.10.10), the arithmetic-coded
238//!     `decode_subexp_bool` (§5.9.28 bool variant), and §8.2.4
239//!     `exit_symbol` (trailing-bit accounting + byte-alignment advance,
240//!     rejecting the `SymbolMaxBits < -14` conformance violation via
241//!     [`Error::SymbolExitUnderflow`]). The default CDF tables (§9.4)
242//!     and the §8.3.2 CDF-selection process are out of scope this round —
243//!     they land with the tile-content decode that consumes them. See
244//!     [`symbol_decoder`].
245//!
246//!   * **Round 16.** The §9.4 default CDF tables and the §8.3.1 /
247//!     §8.3.2 CDF-selection process for a bounded **intra-frame mode /
248//!     partition** syntax group, in a new [`cdf`] module. Transcribes
249//!     [`DEFAULT_INTRA_FRAME_Y_MODE_CDF`] (the `intra_frame_y_mode`
250//!     5×5×14 table), the five `DEFAULT_PARTITION_W{8,16,32,64,128}_CDF`
251//!     tables (the `partition` element), [`DEFAULT_SKIP_CDF`], and
252//!     [`DEFAULT_SEGMENT_ID_CDF`] verbatim from §9.4. [`TileCdfContext`]
253//!     implements §8.3.1 (`new_from_defaults` copies every `Default_*`
254//!     table into a per-tile, mutable `Tile*Cdf` working set that the
255//!     §8.2 [`SymbolDecoder`] adapts in place), and the §8.3.2 selection
256//!     surfaces a `&mut [u16]` row for each element — `intra_frame_y_mode`
257//!     (`[abovemode][leftmode]`), `partition` (array-by-`bsl`, row-by-`ctx`),
258//!     `skip` (`[ctx]`), and `segment_id` (`[ctx]`) — feeding
259//!     [`SymbolDecoder::read_symbol`] directly. The scalar §8.3.2
260//!     context-derivation helpers ([`intra_mode_ctx`] / [`partition_ctx`]
261//!     / [`skip_ctx`] / [`segment_id_ctx`]) compute the index from
262//!     neighbour inputs the (future) tile walk supplies. The remaining
263//!     ~100 §9.4 tables, the `init_coeff_cdfs` coefficient set, and the
264//!     other §8.3.2 selections (`split_or_horz` / `split_or_vert` /
265//!     `tx_depth` / `txfm_split` / the motion-vector + uv-mode groups)
266//!     are a clear followup. See [`cdf`].
267//!
268//!   * **Round 17.** The §9.4 default CDF tables and the §8.3.1 /
269//!     §8.3.2 CDF-selection process for the **motion-vector component**
270//!     syntax group, extending [`cdf`]. Transcribes
271//!     [`DEFAULT_MV_JOINT_CDF`], [`DEFAULT_MV_SIGN_CDF`],
272//!     [`DEFAULT_MV_CLASS_CDF`], [`DEFAULT_MV_CLASS0_BIT_CDF`],
273//!     [`DEFAULT_MV_CLASS0_FR_CDF`], [`DEFAULT_MV_CLASS0_HP_CDF`],
274//!     [`DEFAULT_MV_BIT_CDF`], [`DEFAULT_MV_FR_CDF`], and
275//!     [`DEFAULT_MV_HP_CDF`] verbatim from §9.4 (the `216*128` /
276//!     `136*128` / … fixed-point notation expanded). [`TileCdfContext`]
277//!     grows nine `mv_*` working-set fields broadcast per §8.3.1 to
278//!     `MV_CONTEXTS = 2` slots (and to the `comp = 0..1` axis where the
279//!     source default is per-comp identical), and the §8.3.2 selection
280//!     surfaces `&mut [u16]` rows for every MV element: `mv_joint`
281//!     (`[MvCtx]`), `mv_sign` / `mv_class` / `mv_class0_bit` /
282//!     `mv_class0_hp` / `mv_fr` / `mv_hp` (`[MvCtx][comp]`),
283//!     `mv_class0_fr` (`[MvCtx][comp][mv_class0_bit]`), and `mv_bit`
284//!     (`[MvCtx][comp][i]`). The §5.11.31 `MvCtx` derivation —
285//!     `MvCtx = use_intrabc ? MV_INTRABC_CONTEXT : 0` — is exposed as
286//!     the [`mv_ctx`] helper. The remaining ~90 §9.4 tables (y_mode,
287//!     uv_mode, angle-delta, tx-size, coefficient, palette, …) and the
288//!     other §8.3.2 selections are a mechanical followup against the
289//!     same [`TileCdfContext`] shape.
290//!
291//!   * **Round 18.** The §9.4 default CDF tables and the §8.3.1 /
292//!     §8.3.2 selection for the **inter-mode / reference-frame**
293//!     syntax group, extending [`cdf`]. Transcribes the 13 remaining
294//!     `Default_*_Cdf` tables driving every inter-block mode and
295//!     reference syntax: [`DEFAULT_NEW_MV_CDF`], [`DEFAULT_ZERO_MV_CDF`],
296//!     [`DEFAULT_REF_MV_CDF`], [`DEFAULT_DRL_MODE_CDF`],
297//!     [`DEFAULT_IS_INTER_CDF`], [`DEFAULT_COMP_MODE_CDF`],
298//!     [`DEFAULT_SKIP_MODE_CDF`], [`DEFAULT_COMP_REF_CDF`],
299//!     [`DEFAULT_COMP_BWD_REF_CDF`], [`DEFAULT_SINGLE_REF_CDF`],
300//!     [`DEFAULT_COMPOUND_MODE_CDF`], [`DEFAULT_COMP_REF_TYPE_CDF`],
301//!     [`DEFAULT_UNI_COMP_REF_CDF`] verbatim from §9.4, plus the §8.3.2
302//!     [`COMPOUND_MODE_CTX_MAP`] lookup table. [`TileCdfContext`] grows
303//!     the corresponding `Tile*Cdf` fields, [`TileCdfContext::new_from_defaults`]
304//!     seeds them per §8.3.1, and the §8.3.2 selection surfaces
305//!     `&mut [u16]` rows for every element: `new_mv_cdf` / `zero_mv_cdf` /
306//!     `ref_mv_cdf` / `drl_mode_cdf` / `is_inter_cdf` / `comp_mode_cdf` /
307//!     `skip_mode_cdf` / `comp_ref_cdf` / `comp_bwd_ref_cdf` /
308//!     `single_ref_cdf` / `compound_mode_cdf` / `comp_ref_type_cdf` /
309//!     `uni_comp_ref_cdf`. Scalar §8.3.2 context helpers
310//!     [`is_inter_ctx`] (the `(AvailU, AvailL) × (AboveIntra, LeftIntra)`
311//!     branch ladder), [`skip_mode_ctx`] (neighbour `SkipModes[]` sum),
312//!     [`ref_count_ctx`] (`<` / `==` / `>` three-branch shared by every
313//!     `single_ref_p*` / `comp_ref` / `comp_bwdref` / `uni_comp_ref_p*`
314//!     paragraph), and [`compound_mode_ctx`] (`Compound_Mode_Ctx_Map`
315//!     lookup) compute each `ctx` from the neighbour-summary inputs the
316//!     (future) tile walk supplies.
317//!
318//!   * **Round 20.** The §9.4 default CDF tables and the §8.3.1 /
319//!     §8.3.2 selection for the **transform-size** syntax group,
320//!     extending [`cdf`]. Transcribes the four per-`maxTxDepth`
321//!     `tx_depth` tables ([`DEFAULT_TX_8X8_CDF`], [`DEFAULT_TX_16X16_CDF`],
322//!     [`DEFAULT_TX_32X32_CDF`], [`DEFAULT_TX_64X64_CDF`]) and the
323//!     binary [`DEFAULT_TXFM_SPLIT_CDF`] verbatim from §9.4.
324//!     [`TileCdfContext`] grows the `tx_8x8` / `tx_16x16` /
325//!     `tx_32x32` / `tx_64x64` / `txfm_split` fields, all seeded by
326//!     [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
327//!     selection surfaces two `&mut [u16]` accessors —
328//!     `tx_depth_cdf(maxTxDepth, ctx)` (the §8.3.2 four-way
329//!     `TileTx{8x8,16x16,32x32,64x64}Cdf[ ctx ]` switch keyed by
330//!     `Max_Tx_Depth[ MiSize ]`; returns `None` when
331//!     `maxTxDepth == 0`) and `txfm_split_cdf(ctx)`. Scalar §8.3.2
332//!     context helpers [`tx_depth_ctx`] (the
333//!     `(aboveW >= maxTxWidth) + (leftH >= maxTxHeight)` formula) and
334//!     [`txfm_split_ctx`] (the
335//!     `(txSzSqrUp != maxTxSz) * 3 + (TX_SIZES - 1 - maxTxSz) * 6 +
336//!     above + left` formula) compute each `ctx` from scalar inputs
337//!     the §5.11.15 / §5.11.16 syntax supplies.
338//!
339//!   * **Round 21.** The §9.4 default CDF tables and the §8.3.1 /
340//!     §8.3.2 selection for the **inter-frame transform-type** syntax
341//!     group, extending [`cdf`]. Transcribes the three
342//!     `Default_Inter_Tx_Type_Set{1,2,3}_Cdf` tables
343//!     ([`DEFAULT_INTER_TX_TYPE_SET1_CDF`],
344//!     [`DEFAULT_INTER_TX_TYPE_SET2_CDF`],
345//!     [`DEFAULT_INTER_TX_TYPE_SET3_CDF`]) verbatim from §9.4 —
346//!     `Set1` for the full 16-symbol set (4x4 / 8x8 inter blocks),
347//!     `Set2` for the 16x16 inter set (12 symbols), `Set3` for the
348//!     reduced 2-symbol `{ IDTX, DCT_DCT }` set (4x4..32x32 inter
349//!     blocks). [`TileCdfContext`] grows the `inter_tx_type_set1` /
350//!     `inter_tx_type_set2` / `inter_tx_type_set3` fields, all
351//!     seeded by [`TileCdfContext::new_from_defaults`] per §8.3.1.
352//!     The §8.3.2 selection surfaces an `&mut [u16]` accessor
353//!     `inter_tx_type_cdf(set, tx_size_sqr)` (the §8.3.2 three-way
354//!     `TX_SET_INTER_{1,2,3}` switch; returns `None` for
355//!     `TX_SET_DCTONLY` per §5.11.47 and for any unreachable
356//!     `(set, tx_size_sqr)` combination). The scalar §5.11.48 helper
357//!     [`inter_tx_type_set`] computes the `set ∈ { TX_SET_DCTONLY,
358//!     TX_SET_INTER_1, TX_SET_INTER_2, TX_SET_INTER_3 }` from the
359//!     `(Tx_Size_Sqr[txSz], Tx_Size_Sqr_Up[txSz], reduced_tx_set)`
360//!     tuple supplied by the surrounding §5.11.47 syntax. The intra
361//!     counterpart (`Default_Intra_Tx_Type_Set{1,2}_Cdf` with their
362//!     extra `intraDir` axis) and the remaining §9.4 tables (y_mode,
363//!     uv_mode, angle-delta, coefficient, …) are mechanical
364//!     followups against the same [`TileCdfContext`] shape.
365//!
366//!   * **Round 22.** The §9.4 default CDF table and the §8.3.1 /
367//!     §8.3.2 selection for the **inter-frame interpolation-filter**
368//!     syntax element, extending [`cdf`]. Transcribes
369//!     [`DEFAULT_INTERP_FILTER_CDF`] — `[INTERP_FILTER_CONTEXTS][INTERP_FILTERS + 1]`,
370//!     i.e. 16 contexts × 3 cumulative frequencies + adaptation counter
371//!     — verbatim from §9.4. New §3 constants `INTERP_FILTERS = 3`
372//!     and `INTERP_FILTER_CONTEXTS = 16`. [`TileCdfContext`] grows the
373//!     `interp_filter` field, seeded by [`TileCdfContext::new_from_defaults`]
374//!     per §8.3.1. The §8.3.2 selection surfaces
375//!     `interp_filter_cdf(ctx)`; the scalar [`interp_filter_ctx`]
376//!     helper folds the §8.3.2 four-branch
377//!     `(above_type, left_type, dir, is_compound)` formula into a
378//!     single `0..INTERP_FILTER_CONTEXTS` index (the caller supplies
379//!     the already-resolved neighbour-type values per the spec's
380//!     `RefFrame[0]` matching predicate). Sentinel
381//!     [`INTERP_FILTER_NONE`] (== `INTERP_FILTERS`, mirroring the
382//!     spec's literal `3`) marks an unavailable / mismatched neighbour.
383//!
384//!   * **Round 23.** The §9.4 default CDF table and the §8.3.1 /
385//!     §8.3.2 selection for the **motion-mode** syntax element,
386//!     extending [`cdf`]. Transcribes [`DEFAULT_MOTION_MODE_CDF`] —
387//!     `[BLOCK_SIZES][MOTION_MODES + 1]`, i.e. 22 block-size rows × 3
388//!     cumulative frequencies + adaptation counter — verbatim from
389//!     §9.4. New §3 constant `MOTION_MODES = 3` (per §6.10.26
390//!     `SIMPLE = 0` / `OBMC = 1` / `LOCALWARP = 2`). [`TileCdfContext`]
391//!     grows the `motion_mode` field, seeded by
392//!     [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
393//!     selection surfaces `motion_mode_cdf(mi_size)` — a straight
394//!     `0..BLOCK_SIZES` index (the spec's selection text reads
395//!     "`TileMotionModeCdf[ MiSize ]`"; no neighbour-context
396//!     arithmetic).
397//!
398//!   * **Round 24.** The §9.4 default CDF tables and the §8.3.1 /
399//!     §8.3.2 selection for the **compound-prediction** syntax
400//!     elements, extending [`cdf`]. Transcribes
401//!     [`DEFAULT_COMP_GROUP_IDX_CDF`] (`[COMP_GROUP_IDX_CONTEXTS][3]`),
402//!     [`DEFAULT_COMPOUND_IDX_CDF`] (`[COMPOUND_IDX_CONTEXTS][3]`) and
403//!     [`DEFAULT_COMPOUND_TYPE_CDF`]
404//!     (`[BLOCK_SIZES][COMPOUND_TYPES + 1]`) verbatim from §9.4. New §3
405//!     constants `COMPOUND_TYPES = 2`, `COMP_GROUP_IDX_CONTEXTS = 6`,
406//!     `COMPOUND_IDX_CONTEXTS = 6`. [`TileCdfContext`] grows the
407//!     `comp_group_idx` / `compound_idx` / `compound_type` fields,
408//!     seeded by [`TileCdfContext::new_from_defaults`] per §8.3.1. The
409//!     §8.3.2 selection surfaces `comp_group_idx_cdf(ctx)` /
410//!     `compound_idx_cdf(ctx)` (binary, precomputed-`ctx` index) and
411//!     `compound_type_cdf(mi_size)` (a straight `0..BLOCK_SIZES` index;
412//!     the spec's selection text reads "`TileCompoundTypeCdf[ MiSize
413//!     ]`").
414//!
415//!   * **Round 134.** The §9.4 default CDF tables and the §8.3.1 /
416//!     §8.3.2 selection for the inter-frame **intra-mode** syntax
417//!     elements, extending [`cdf`]. Transcribes [`DEFAULT_Y_MODE_CDF`]
418//!     (`[BLOCK_SIZE_GROUPS][INTRA_MODES + 1]`),
419//!     [`DEFAULT_UV_MODE_CFL_NOT_ALLOWED_CDF`]
420//!     (`[INTRA_MODES][UV_INTRA_MODES_CFL_NOT_ALLOWED + 1]`) and
421//!     [`DEFAULT_UV_MODE_CFL_ALLOWED_CDF`]
422//!     (`[INTRA_MODES][UV_INTRA_MODES_CFL_ALLOWED + 1]`) verbatim from
423//!     §9.4. New §3 constants `BLOCK_SIZE_GROUPS = 4`,
424//!     `UV_INTRA_MODES_CFL_NOT_ALLOWED = 13`,
425//!     `UV_INTRA_MODES_CFL_ALLOWED = 14` plus the §8.3.2
426//!     [`SIZE_GROUP`] table. [`TileCdfContext`] grows the `y_mode` /
427//!     `uv_mode_cfl_not_allowed` / `uv_mode_cfl_allowed` fields, seeded
428//!     by [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
429//!     selection surfaces `y_mode_cdf(ctx)` (with [`size_group`]
430//!     performing the `ctx = Size_Group[ MiSize ]` mapping) and
431//!     `uv_mode_cdf(cfl_allowed, y_mode)` (picking the cfl-allowed /
432//!     cfl-not-allowed variant by the resolved flag, then indexing by
433//!     `YMode`).
434//!
435//!   * **Round 135.** The §9.4 default CDF table and the §8.3.1 /
436//!     §8.3.2 selection for the **angle-delta** syntax elements
437//!     (`angle_delta_y` / `angle_delta_uv`), extending [`cdf`].
438//!     Transcribes [`DEFAULT_ANGLE_DELTA_CDF`]
439//!     (`[DIRECTIONAL_MODES][(2 * MAX_ANGLE_DELTA + 1) + 1]`) verbatim
440//!     from §9.4. New §3 constants `DIRECTIONAL_MODES = 8`,
441//!     `MAX_ANGLE_DELTA = 3` and the directional-mode base `V_PRED = 1`.
442//!     [`TileCdfContext`] grows the `angle_delta` field, seeded by
443//!     [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
444//!     selection surfaces `angle_delta_cdf(mode)`, which rebases a
445//!     directional `YMode` / `UVMode` onto `0..DIRECTIONAL_MODES` via
446//!     `mode - V_PRED` (the `TileAngleDeltaCdf[ YMode - V_PRED ]` /
447//!     `TileAngleDeltaCdf[ UVMode - V_PRED ]` selection).
448//!   * **Round 136.** The §9.4 default CDF tables and the §8.3.1
449//!     `init_coeff_cdfs` / §8.3.2 selection for the **coefficient-token
450//!     entry sub-group** — the gateway to tile-content decode: the
451//!     transform-block skip flag ([`DEFAULT_TXB_SKIP_CDF`]), the
452//!     end-of-block position class
453//!     ([`DEFAULT_EOB_PT_16_CDF`] … [`DEFAULT_EOB_PT_1024_CDF`]), the
454//!     EOB extra-bit ([`DEFAULT_EOB_EXTRA_CDF`]), and the DC sign
455//!     ([`DEFAULT_DC_SIGN_CDF`]), all transcribed verbatim from §9.4.
456//!     New §3 constants `PLANE_TYPES = 2`, `COEFF_CDF_Q_CTXS = 4`,
457//!     `TXB_SKIP_CONTEXTS = 13`, `EOB_COEF_CONTEXTS = 9`,
458//!     `DC_SIGN_CONTEXTS = 3`. Unlike the non-coeff CDFs, these are
459//!     reset by the separate [`TileCdfContext::init_coeff_cdfs`]
460//!     (`base_q_idx` → `idx` via [`coeff_cdf_q_ctx`]) so the working
461//!     copy drops the `COEFF_CDF_Q_CTXS` axis, selecting
462//!     `Default_*_Cdf[ idx ]`. The coeff_base / coeff_base_eob /
463//!     coeff_br braid is deferred to a later round.
464//!
465//!   * **Round 137.** The §9.4 default CDF tables and the §8.3.1 /
466//!     §8.3.2 selection for the **intra-frame transform-type** syntax
467//!     group, completing the §6.10.19 transform-set coverage started
468//!     in round 21. Transcribes [`DEFAULT_INTRA_TX_TYPE_SET1_CDF`]
469//!     (`[INTRA_TX_TYPE_SET1_SIZES][INTRA_MODES][TX_TYPES_INTRA_SET1 + 1]`,
470//!     i.e. `[2][13][8]` per the §9.4 listing) and
471//!     [`DEFAULT_INTRA_TX_TYPE_SET2_CDF`]
472//!     (`[INTRA_TX_TYPE_SET2_SIZES][INTRA_MODES][TX_TYPES_INTRA_SET2 + 1]`,
473//!     i.e. `[3][13][6]`) verbatim from §9.4 — `Set1` for the full
474//!     7-symbol intra set (4x4 / 8x8 intra blocks), `Set2` for the
475//!     reduced 5-symbol set (4x4 / 8x8 / 16x16 intra blocks). Both
476//!     tables carry an extra `intraDir` axis (`INTRA_MODES = 13`) on
477//!     top of the `Tx_Size_Sqr` axis already seen in the inter
478//!     counterparts. New §3 constants `TX_SET_INTRA_1 = 1`,
479//!     `TX_SET_INTRA_2 = 2`, `TX_TYPES_INTRA_SET1 = 7`,
480//!     `TX_TYPES_INTRA_SET2 = 5`, `INTRA_TX_TYPE_SET1_SIZES = 2`,
481//!     `INTRA_TX_TYPE_SET2_SIZES = 3`, and the §8.3.2
482//!     [`FILTER_INTRA_MODE_TO_INTRA_DIR`] table. [`TileCdfContext`]
483//!     grows the `intra_tx_type_set1` / `intra_tx_type_set2` fields,
484//!     seeded by [`TileCdfContext::new_from_defaults`] per §8.3.1.
485//!     The §8.3.2 selection surfaces an `&mut [u16]` accessor
486//!     `intra_tx_type_cdf(set, tx_size_sqr, intra_dir)` (the §8.3.2
487//!     two-way `TX_SET_INTRA_{1,2}` switch over the §8.3.2
488//!     `intraDir` axis; returns `None` for `TX_SET_DCTONLY` per
489//!     §5.11.47 and for any unreachable `(set, tx_size_sqr,
490//!     intra_dir)` combination). The scalar §5.11.48 helper
491//!     [`intra_tx_type_set`] computes the `set ∈ { TX_SET_DCTONLY,
492//!     TX_SET_INTRA_1, TX_SET_INTRA_2 }` from the `(Tx_Size_Sqr[txSz],
493//!     Tx_Size_Sqr_Up[txSz], reduced_tx_set)` tuple supplied by the
494//!     surrounding §5.11.47 syntax (the intra branch differs from the
495//!     inter one in two places: `txSzSqrUp == TX_32X32` itself routes
496//!     to `TX_SET_DCTONLY` rather than `TX_SET_INTER_3`, and the
497//!     `txSzSqr == TX_16X16` branch routes to `TX_SET_INTRA_2`
498//!     rather than `TX_SET_INTER_2`). The scalar §8.3.2 helper
499//!     [`intra_dir`] derives the `intraDir` axis from the
500//!     `use_filter_intra` flag plus the `YMode` / `filter_intra_mode`
501//!     pair.
502//!
503//!   * **Round 138.** The §9.4 default CDF table and the §8.3.1
504//!     `init_coeff_cdfs` / §8.3.2 selection for the first member of the
505//!     `coeff_base` / `coeff_base_eob` / `coeff_br` braid:
506//!     [`DEFAULT_COEFF_BASE_EOB_CDF`]
507//!     (`[COEFF_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][4]`),
508//!     transcribed verbatim from §9.4. `coeff_base_eob` codes the base
509//!     level of the last non-zero coefficient (the base level is
510//!     `coeff_base_eob + 1`; only 1, 2, or 3 are coded). New §3
511//!     constant `SIG_COEF_CONTEXTS_EOB = 4`. [`TileCdfContext`] grows
512//!     the `coeff_base_eob` field, seeded by
513//!     [`TileCdfContext::new_from_defaults`] from the `idx == 0`
514//!     slice and re-selected per `base_q_idx` by
515//!     [`TileCdfContext::init_coeff_cdfs`]. The §8.3.2 selection
516//!     surfaces `coeff_base_eob_cdf(tx_sz_ctx, ptype, ctx)`, the
517//!     three-way `TileCoeffBaseEobCdf[ txSzCtx ][ ptype ][ ctx ]`
518//!     lookup; the §8.3.2 ctx derivation
519//!     (`get_coeff_base_ctx() - SIG_COEF_CONTEXTS + SIG_COEF_CONTEXTS_EOB`)
520//!     belongs to the not-yet-implemented tile-content walk and is
521//!     deferred. The remaining two tables of the braid
522//!     (`Default_Coeff_Base_Cdf` and `Default_Coeff_Br_Cdf`) are
523//!     deferred to later rounds.
524//!
525//!   * **Round 139.** The §9.4 default CDF table and the §8.3.1
526//!     `init_coeff_cdfs` / §8.3.2 selection for the second member of
527//!     the `coeff_base` / `coeff_base_eob` / `coeff_br` braid:
528//!     [`DEFAULT_COEFF_BASE_CDF`]
529//!     (`[COEFF_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS][5]`,
530//!     1680 5-entry rows; declared `static` so `clippy::large_const_arrays`
531//!     does not flag the per-use copy hazard), transcribed verbatim
532//!     from §9.4. `coeff_base` codes the base level of each non-EOB
533//!     coefficient — a 4-symbol alphabet (`0..3`). New §3 constant
534//!     `SIG_COEF_CONTEXTS = 42`. [`TileCdfContext`] grows the
535//!     `coeff_base` field, seeded by
536//!     [`TileCdfContext::new_from_defaults`] from the `idx == 0`
537//!     slice and re-selected per `base_q_idx` by
538//!     [`TileCdfContext::init_coeff_cdfs`]. The §8.3.2 selection
539//!     surfaces `coeff_base_cdf(tx_sz_ctx, ptype, ctx)`, the
540//!     three-way `TileCoeffBaseCdf[ txSzCtx ][ ptype ][ ctx ]`
541//!     lookup; the `get_coeff_base_ctx()` derivation itself belongs
542//!     to the not-yet-implemented tile-content walk and is deferred.
543//!     The largest `(TX_SIZE = TX_64X64, ptype = chroma)` slice is
544//!     a flat `{8192, 16384, 24576, 32768, 0}` placeholder across
545//!     every q-context and ctx value (an unreachable-chroma sentinel
546//!     mirroring the r138 (tx4, pt1) placeholder pattern). The last
547//!     remaining table of the braid (`Default_Coeff_Br_Cdf`) is
548//!     deferred to a later round.
549//!
550//!   * **Round 140.** The §9.4 default CDF table and the §8.3.1
551//!     `init_coeff_cdfs` / §8.3.2 selection for the LAST member of
552//!     the `coeff_base` / `coeff_base_eob` / `coeff_br` braid:
553//!     [`DEFAULT_COEFF_BR_CDF`]
554//!     (`[COEFF_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][BR_CDF_SIZE + 1]`,
555//!     840 5-entry rows; declared `static` so `clippy::large_const_arrays`
556//!     does not flag the per-use copy hazard), transcribed verbatim
557//!     from §9.4. With this table all three coefficient-CDF braid
558//!     members are landed. `coeff_br` codes the per-coefficient
559//!     base-range increment used to push a level above
560//!     `NUM_BASE_LEVELS`: each read codes a value in
561//!     `0..BR_CDF_SIZE = 4`, and §5.11.39 stacks
562//!     `COEFF_BASE_RANGE / (BR_CDF_SIZE - 1)` such reads per
563//!     coefficient. New §3 constants `LEVEL_CONTEXTS = 21` and
564//!     `BR_CDF_SIZE = 4`. [`TileCdfContext`] grows the `coeff_br`
565//!     field, seeded by [`TileCdfContext::new_from_defaults`] from
566//!     the `idx == 0` slice and re-selected per `base_q_idx` by
567//!     [`TileCdfContext::init_coeff_cdfs`]. The §8.3.2 selection
568//!     surfaces `coeff_br_cdf(tx_sz_ctx, ptype, ctx)`, implementing
569//!     the spec selector
570//!     `TileCoeffBrCdf[ Min(txSzCtx, TX_32X32) ][ ptype ][ ctx ]`
571//!     with the `TX_32X32 = 3` clamp built in (so any `txSzCtx` is
572//!     accepted; only `ptype` / `ctx` are bounds-checked); the
573//!     `get_br_ctx()` derivation itself belongs to the
574//!     not-yet-implemented tile-content walk and is deferred. The
575//!     largest `(TX_SIZE = TX_64X64, ptype = chroma)` slice is again
576//!     a flat `{8192, 16384, 24576, 32768, 0}` placeholder, mirroring
577//!     the r138 / r139 pattern. The next gate is the §8.3.2
578//!     `get_coeff_base_ctx()` / `get_br_ctx()` neighbour-derivation
579//!     helpers (deferred to a different round — they need
580//!     tile-content walker state).
581//!
582//!   * **Round 141.** The §8.3.2 neighbour-derivation helpers that
583//!     close out the coefficient-CDF braid: [`get_coeff_base_ctx`]
584//!     and [`get_br_ctx`] (plus the [`get_coeff_base_eob_ctx`]
585//!     wrapper that subtracts `SIG_COEF_CONTEXTS` and adds
586//!     `SIG_COEF_CONTEXTS_EOB` to land on the EOB-CDF context
587//!     range). Each consumes a coefficient-magnitude array `Quant[]`
588//!     (laid out row-major with stride `Tx_Width[ adjTxSz ]`) plus
589//!     the position-in-scan + tx-class + tx-size and returns the
590//!     `ctx` index consumed by the matching `coeff_base_eob_cdf` /
591//!     `coeff_base_cdf` / `coeff_br_cdf` selector. [`get_tx_class`]
592//!     performs the §8.3.2 `TxType -> TxClass` reduction
593//!     (`V_DCT` / `V_ADST` / `V_FLIPADST` -> [`TX_CLASS_VERT`],
594//!     `H_DCT` / `H_ADST` / `H_FLIPADST` -> [`TX_CLASS_HORIZ`],
595//!     everything else -> [`TX_CLASS_2D`]). New §3 constants
596//!     [`TX_SIZES_ALL`] (`= 19`), [`SIG_COEF_CONTEXTS_2D`] (`= 26`),
597//!     [`SIG_REF_DIFF_OFFSET_NUM`] (`= 5`), [`NUM_BASE_LEVELS`]
598//!     (`= 2`), [`COEFF_BASE_RANGE`] (`= 12`), [`TX_CLASS_2D`],
599//!     [`TX_CLASS_HORIZ`], [`TX_CLASS_VERT`]. New §-Additional-
600//!     tables transcriptions [`TX_WIDTH`], [`TX_HEIGHT`],
601//!     [`TX_WIDTH_LOG2`], [`ADJUSTED_TX_SIZE`],
602//!     [`SIG_REF_DIFF_OFFSET`], [`MAG_REF_OFFSET_WITH_TX_CLASS`],
603//!     [`COEFF_BASE_CTX_OFFSET`], [`COEFF_BASE_POS_CTX_OFFSET`].
604//!     Caller still owns the tile-content walk that supplies
605//!     `Quant[]` itself plus the `compute_tx_type()` derivation that
606//!     feeds [`get_tx_class`]; this round delivers the per-coefficient
607//!     `ctx` plumbing those callers will consume.
608//!
609//!   * **Round 142.** The §5.11.40 `compute_tx_type()` derivation —
610//!     [`compute_tx_type`], the per-plane / per-block transform-type
611//!     lookup the tile-content walker reads before kicking off
612//!     coefficient decoding. Implements the full spec function:
613//!     `Lossless || Tx_Size_Sqr_Up[ txSz ] > TX_32X32` short-circuits
614//!     to `DCT_DCT`; `plane == 0` returns the `TxTypes[ blockY ][
615//!     blockX ]` luma cache entry; `is_inter` chroma reads the cache
616//!     at `(Max(MiRow, blockY << subsampling_y),
617//!     Max(MiCol, blockX << subsampling_x))` then runs the
618//!     [`is_tx_type_in_set`] admission filter; intra chroma reads
619//!     [`MODE_TO_TXFM`]`[UVMode]` then runs the same filter. The
620//!     §5.11.40 `is_tx_type_in_set(txSet, txType)` predicate is a
621//!     direct read of [`TX_TYPE_IN_SET_INTER`] /
622//!     [`TX_TYPE_IN_SET_INTRA`]. The caller supplies the §5.11.40
623//!     `txSet` (i.e. the already-resolved [`inter_tx_type_set`] /
624//!     [`intra_tx_type_set`] result) and a closure over
625//!     `TxTypes[y][x]` so the helper does not bake in a particular
626//!     storage shape. New §6.10.16 ordinal constants [`TX_4X4`] /
627//!     [`TX_8X8`] / [`TX_16X16`] / [`TX_32X32`] / [`TX_64X64`]
628//!     replace the local `const TX_*` shadows the existing
629//!     [`inter_tx_type_set`] / [`intra_tx_type_set`] helpers used.
630//!     New §6.10.19 transform-type ordinals [`DCT_DCT`] through
631//!     [`H_FLIPADST`] (16 entries) name the previously-numeric
632//!     entries. New §-Additional-tables transcription
633//!     [`TX_SIZE_SQR_UP`] (`Tx_Size_Sqr_Up[ TX_SIZES_ALL ]`,
634//!     `t -> Max(w, h)-sided square`). New §5.11.40 tables
635//!     [`MODE_TO_TXFM`] (chroma-mode -> default transform-type),
636//!     [`TX_TYPE_IN_SET_INTRA`] (`TX_SET_TYPES_INTRA = 3` rows of
637//!     `TX_TYPES = 16` admission flags), [`TX_TYPE_IN_SET_INTER`]
638//!     (`TX_SET_TYPES_INTER = 4` rows). The derivation is pure / msac-
639//!     independent — the tile walker plugs it in once `MiRow` /
640//!     `MiCol` / `subsampling_x` / `subsampling_y` / `UVMode` /
641//!     `TxTypes` state lands. 278 -> 288 tests, zero `#[ignore]`.
642//!
643//!   * **Round 143.** The §9.4 default CDF tables and the §8.3.1 /
644//!     §8.3.2 selection for the **inter-intra** syntax group
645//!     (`interintra`, `interintra_mode`, `wedge_interintra` — the
646//!     §5.11.28 `read_interintra_mode` triple). Transcribes
647//!     [`DEFAULT_INTER_INTRA_CDF`] (`[BLOCK_SIZE_GROUPS - 1][3]`),
648//!     [`DEFAULT_INTER_INTRA_MODE_CDF`]
649//!     (`[BLOCK_SIZE_GROUPS - 1][INTERINTRA_MODES + 1]`) and
650//!     [`DEFAULT_WEDGE_INTER_INTRA_CDF`] (`[BLOCK_SIZES][3]`) verbatim
651//!     from §9.4. New §3 constant [`INTERINTRA_MODES`] (`= 4`, per
652//!     §6.10.27 `II_DC_PRED` / `II_V_PRED` / `II_H_PRED` /
653//!     `II_SMOOTH_PRED`). [`TileCdfContext`] grows the `inter_intra` /
654//!     `inter_intra_mode` / `wedge_inter_intra` fields, seeded by
655//!     [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
656//!     selection surfaces `inter_intra_cdf(ctx)` /
657//!     `inter_intra_mode_cdf(ctx)` (the scalar [`interintra_ctx`]
658//!     helper folds the spec's `ctx = Size_Group[ MiSize ] - 1` into a
659//!     single `0..(BLOCK_SIZE_GROUPS - 1)` index, returning `None` for
660//!     the `Size_Group[ MiSize ] == 0` rows that the §5.11.28 syntax
661//!     gate excludes) and `wedge_inter_intra_cdf(mi_size)` (a straight
662//!     `0..BLOCK_SIZES` index). The wedge table's outer dimension is
663//!     transcribed full-width per the §9.4 listing; per its note only
664//!     indices `3..=9` (the `BLOCK_8X8`..`BLOCK_32X32` band) are
665//!     reachable. 288 -> 296 tests, zero `#[ignore]`.
666//!
667//!   * **Round 144.** The §9.4 default CDF table and the §8.3.1 /
668//!     §8.3.2 selection for the **wedge-index** syntax element —
669//!     `wedge_index`, read by both §5.11.28 `read_interintra_mode` (the
670//!     inter-intra wedge sub-branch, when `wedge_interintra == 1`) and
671//!     §5.11.29 `read_compound_type` (the inter-inter `COMPOUND_WEDGE`
672//!     branch). Transcribes [`DEFAULT_WEDGE_INDEX_CDF`]
673//!     (`[BLOCK_SIZES][WEDGE_TYPES + 1]`) verbatim from §9.4 (p.435).
674//!     New §3 constant [`WEDGE_TYPES`] (`= 16`, the spec text reads
675//!     *"Number of directions for the wedge mask process"*).
676//!     [`TileCdfContext`] grows the `wedge_index` field, seeded by
677//!     [`TileCdfContext::new_from_defaults`] per §8.3.1. The §8.3.2
678//!     selection `wedge_index_cdf(mi_size)` is a straight
679//!     `TileWedgeIndexCdf[ MiSize ]` index. The table's outer dimension
680//!     is transcribed full-width per the §9.4 listing; per its note
681//!     (p.436) indices 0..2, 10..17, and 20..21 are never used in the
682//!     first dimension (matching the §3 `Wedge_Bits[ MiSize ] == 0`
683//!     rows) and carry the placeholder uniform CDF `{ 2048, 4096, …,
684//!     30720, 32768, 0 }` (step `32768 / WEDGE_TYPES`). 296 -> 302
685//!     tests, zero `#[ignore]`.
686//!
687//!   * **Round 145.** The §8.3.2 `split_or_horz` / `split_or_vert`
688//!     cdf-derivation helpers — [`split_or_horz_cdf`] and
689//!     [`split_or_vert_cdf`] — that build a 2-symbol binary cdf out of
690//!     the already-selected `partition` cdf (the spec's `partitionCdf`)
691//!     per p.362. Each helper folds the §9.4 partition probabilities of
692//!     the "splittable plus orthogonal-axis" symbols into a single
693//!     `psum`, then emits `cdf[0] = (1 << 15) - psum`,
694//!     `cdf[1] = 1 << 15`, `cdf[2] = 0`; per the §8.3.2 note the
695//!     probability of the disallowed orthogonal partition gets folded
696//!     into the split probability, so `split_or_horz` cannot return a
697//!     `PARTITION_VERT` and `split_or_vert` cannot return a
698//!     `PARTITION_HORZ`. The `b_size != BLOCK_128X128` guard drops the
699//!     `PARTITION_*_4` term that the §9.4 `Default_Partition_W128_Cdf`
700//!     row has no entry for. New §6.10.4 / §3 ordinal constants
701//!     [`PARTITION_NONE`] / [`PARTITION_HORZ`] / [`PARTITION_VERT`] /
702//!     [`PARTITION_SPLIT`] / [`PARTITION_HORZ_A`] / [`PARTITION_HORZ_B`]
703//!     / [`PARTITION_VERT_A`] / [`PARTITION_VERT_B`] /
704//!     [`PARTITION_HORZ_4`] / [`PARTITION_VERT_4`] +
705//!     [`EXT_PARTITION_TYPES`] (`= 10`) + the block-size ordinal
706//!     [`BLOCK_128X128`] (`= 15`) replace the literal indices the §8.3.2
707//!     formulas use. 302 -> 312 tests, zero `#[ignore]`.
708//!
709//!   * **Round 146.** The §5.11.50 `get_palette_color_context`
710//!     derivation — the function the §5.11.49 diagonal walk reads at
711//!     each `palette_color_idx_*` position to produce the
712//!     `ColorOrder[ PALETTE_COLORS ]` permutation +
713//!     `ColorContextHash` that flow back through [`palette_color_ctx`]
714//!     into the §8.3.2 cdf selector. Surface:
715//!     [`palette_color_context_from_neighbors`] (pure-scoring core
716//!     taking the three optional neighbour palette indices) and
717//!     [`get_palette_color_context`] (spec-faithful 2-D entry that
718//!     applies the §5.11.50 `r > 0` / `c > 0` boundary guards). The
719//!     [`PaletteColorContext`] struct packages both outputs. The
720//!     partial selection sort is the §5.11.50 three-iteration loop
721//!     that promotes the top-scoring neighbours to the head of
722//!     `ColorOrder` while preserving the runners-up's ascending
723//!     order; the hash is the `Palette_Color_Hash_Multipliers`-
724//!     weighted sum of the top three sorted scores. 312 -> 323
725//!     tests, zero `#[ignore]`.
726//!
727//!   * **Round 147.** The §5.11.49 `palette_tokens( )` per-plane
728//!     diagonal walker — the §5.11.49 caller-facing entry point that
729//!     drives the §5.11.50 colour-context derivation across one of the
730//!     planes' anti-diagonal walk, decodes one
731//!     `palette_color_idx_{y,uv}` per `(i - j, j)` against the cdf
732//!     row picked by [`palette_color_ctx`], remaps through
733//!     `ColorOrder[idx]`, and fills the on-screen border by
734//!     replicating the last on-screen column / row. Surface:
735//!     [`palette_tokens_plane`] (driving the [`SymbolDecoder`] +
736//!     [`TileCdfContext`]) and the [`PalettePlane`] selector. Two
737//!     new [`Error`] variants surface caller-bug preconditions
738//!     ([`Error::InvalidPaletteWalkArgs`]) and the §5.11.50
739//!     unreachable hash slots ([`Error::PaletteColorContextUnmapped`]).
740//!     323 -> 334 tests, zero `#[ignore]`.
741//!
742//!   * **Round 148.** The §9.3 block-size conversion tables
743//!     (av1-spec p.400–401) — four `BLOCK_SIZES`-indexed lookup
744//!     tables that turn a `MiSize` into block dimensions:
745//!     [`MI_WIDTH_LOG2`], [`MI_HEIGHT_LOG2`], [`NUM_4X4_BLOCKS_WIDE`],
746//!     [`NUM_4X4_BLOCKS_HIGH`], plus the §3 constants
747//!     [`MI_SIZE`] (`4`) and [`MI_SIZE_LOG2`] (`2`). Surface: the
748//!     four tables plus the six `MiSize`-keyed `const fn` accessors
749//!     [`block_width`], [`block_height`], [`num_4x4_blocks_wide`],
750//!     [`num_4x4_blocks_high`], [`mi_width_log2`],
751//!     [`mi_height_log2`]. The `Block_Width[ x ] = 4 *
752//!     Num_4x4_Blocks_Wide[ x ]` spec identity is encoded as the
753//!     `NUM_4X4_BLOCKS_WIDE[ x ] << MI_SIZE_LOG2` shift so the
754//!     identity is not duplicated as a numeric table. These feed the
755//!     §5.11.49 [`palette_tokens_plane`] caller staged in r147 and
756//!     unblock the wider §5.x reconstruction call sites that the
757//!     parser will surface once `read_block` is wired. 334 -> 344
758//!     tests, zero `#[ignore]`.
759//!
760//!   * **Round 149.** The §5.11.49 caller-side argument derivation
761//!     (av1-spec p.101-102) — [`palette_tokens_args`] computes the
762//!     four [`PaletteTokensArgs`] dimensions (`blockWidth`,
763//!     `blockHeight`, `onscreenWidth`, `onscreenHeight`) from the
764//!     parser-scope `(MiSize, MiRow, MiCol, MiRows, MiCols, plane,
765//!     subsampling_x, subsampling_y)` tuple. Reuses the §9.3 tables
766//!     staged in r148 and the §5.11.46 palette gate constant
767//!     [`BLOCK_8X8`] (`3`). Both spec branches handled: the Y branch
768//!     returns the §9.3-driven dimensions clipped by `Min(..,
769//!     (MiRows - MiRow) * MI_SIZE)` / `Min(.., (MiCols - MiCol) *
770//!     MI_SIZE)`, the UV branch applies the `>> subsampling_{x,y}`
771//!     shift then the §5.11.49 `<4`-bump (`block_w += 2; onscreen_w
772//!     += 2` when post-shift `block_w < 4`, ditto for height).
773//!     Walker invariants (`1 <= onscreen_* <= block_*`, `block_* <=
774//!     64`) proven over every palette-eligible `(MiSize, sub_x,
775//!     sub_y, plane)` combination. Bridges the data-flow gap pinned
776//!     by the r147 follow-up test so `read_block` can call
777//!     `palette_tokens` once the parser surfaces it. 344 -> 359
778//!     tests, zero `#[ignore]`.
779//!
780//!   * **Round 150.** The §9.3 `Partition_Subsize[ 10 ][ BLOCK_SIZES ]`
781//!     lookup (av1-spec p.402-403) plus the §3 enumeration of the
782//!     22 named `BLOCK_*` ordinals and the [`BLOCK_INVALID`] (`22`)
783//!     sentinel. [`PARTITION_SUBSIZE`] transcribes the table
784//!     verbatim — every rectangular `bSize` column carries
785//!     `BLOCK_INVALID` per the av1-spec p.401 note "The table will
786//!     never get accessed for rectangular block sizes". The typed
787//!     accessor [`partition_subsize`] folds the sentinel into
788//!     `Option<usize>` (`None` on `BLOCK_INVALID` or out-of-range
789//!     indices) so the upcoming §5.11.4 `decode_partition()` body
790//!     can read `subSize = Partition_Subsize[ partition ][ bSize ]`
791//!     /  `splitSize = Partition_Subsize[ PARTITION_SPLIT ][ bSize ]`
792//!     and never hand a sentinel to its recursive children. Tests
793//!     cover row-3 (SPLIT) halving identity, row-1 (HORZ) / row-2
794//!     (VERT) halving, row-4..7 (`_A` / `_B`) row equality with
795//!     rows 1 / 2, row-8..9 (`_4`) quarter-splits, the
796//!     `BLOCK_4X4`-only-resolves-for-`PARTITION_NONE` column-0
797//!     invariant, exhaustive rectangular-`bSize`-is-invalid
798//!     coverage, and the §5.11.4 subdivision-shrinks-area
799//!     invariant. The 22 `BLOCK_*` constants and `BLOCK_INVALID`
800//!     are also pinned against their av1-spec p.171-172 / p.7
801//!     ordinals. 359 -> 375 tests, zero `#[ignore]`.
802//!
803//!   * **Round 151.** The §5.11.4 `decode_partition( r, c, bSize )`
804//!     body (av1-spec p.61-62) — the recursive partition-tree walker
805//!     that stitches r137-r145's §9.4 partition-default CDFs,
806//!     r145's §8.3.2 [`split_or_horz_cdf`] / [`split_or_vert_cdf`]
807//!     binary-CDF derivation, r150's §9.3 [`PARTITION_SUBSIZE`]
808//!     table + [`partition_subsize`] accessor, and the §9.3
809//!     [`MI_WIDTH_LOG2`] / [`NUM_4X4_BLOCKS_WIDE`] tables into one
810//!     [`PartitionWalker`] type. The walker carries the §6.10.4
811//!     `MiSizes[r][c]` grid (filled at every leaf via the block's
812//!     [`NUM_4X4_BLOCKS_WIDE`] / [`NUM_4X4_BLOCKS_HIGH`] footprint),
813//!     and consults it for the §8.3.2 [`partition_ctx`] derivation
814//!     `above = AvailU && (Mi_Width_Log2[ MiSizes[r-1][c] ] < bsl)` /
815//!     `left  = AvailL && (Mi_Height_Log2[ MiSizes[r][c-1] ] < bsl)`
816//!     on every recursive child (av1-spec p.362). The walker emits a
817//!     [`Vec<DecodedBlockRecord>`] of `(MiRow, MiCol, MiSize)` leaves
818//!     in §5.11.4 syntax order; the actual §5.11.5 `decode_block()`
819//!     body remains out of scope and is the next round's target.
820//!     All four §5.11.4 edge-of-frame branches are honoured: the
821//!     `r >= MiRows || c >= MiCols` early return; the `bSize <
822//!     BLOCK_8X8` short-circuit to `PARTITION_NONE` with no symbol
823//!     read; the `hasCols`-alone branch that reads `split_or_horz`;
824//!     the `hasRows`-alone branch that reads `split_or_vert`; and the
825//!     `!hasRows && !hasCols` fall-through to `PARTITION_SPLIT`. All
826//!     ten partition arms (`NONE` / `HORZ` / `VERT` / `SPLIT` /
827//!     `HORZ_A` / `HORZ_B` / `VERT_A` / `VERT_B` / `HORZ_4` /
828//!     `VERT_4`) dispatch the spec's literal `decode_block` /
829//!     recursive `decode_partition` calls with the appropriate
830//!     `subSize` (the `Partition_Subsize[ partition ][ bSize ]`
831//!     lookup) or `splitSize` (the `Partition_Subsize[ PARTITION_SPLIT
832//!     ][ bSize ]` lookup). New [`TileGeometry`] type carries the
833//!     four §5.11.1 mi-unit tile bounds for the [§5.11.51
834//!     `is_inside`](TileGeometry::is_inside) test. The §5.11.4
835//!     bottom-right edge clip on the optional `HORZ_4` / `VERT_4`
836//!     fourth leaf (`r + quarterBlock4x4 * 3 < MiRows` /
837//!     `c + quarterBlock4x4 * 3 < MiCols`) is applied literally.
838//!     Out-of-range / out-of-tile inputs surface as
839//!     [`Error::PartitionWalkOutOfRange`] (caller-bug only — a
840//!     conformant driver never produces one). Tests cover: single-leaf
841//!     `PARTITION_NONE` for sub-`BLOCK_8X8` block sizes (no symbol
842//!     read); single-leaf and split-emission against the W128
843//!     superblock; recursive descent down to `BLOCK_4X4` leaves; all
844//!     ten partition arms via deterministic CDF setups; the
845//!     edge-of-frame `hasRows`-alone / `hasCols`-alone branches via a
846//!     small mi-cropped frame; the §6.10.4 `MiSizes[]` grid-fill
847//!     invariant (every cell of the leaf's `bh4 * bw4` footprint
848//!     carries `sub_size`); and the §5.11.4 `r >= MiRows ||
849//!     c >= MiCols` early-return invariant. The walker leaves the
850//!     `decode_block` coefficient / motion-vector / reconstruction
851//!     path entirely to the next round.
852//!
853//!   * **Round 152.** The §5.11.11 `read_skip()` syntax element
854//!     (av1-spec p.65) — the per-block `skip` syntax read. Lands as
855//!     a new [`PartitionWalker::decode_skip`] method on the r151
856//!     walker, plus a `Skips[r][c]` flag grid carried alongside the
857//!     existing §6.10.4 `MiSizes[]` grid. Both spec branches are
858//!     honoured: when the caller passes `seg_skip_active = true`
859//!     (the combined precondition `SegIdPreSkip &&
860//!     seg_feature_active( SEG_LVL_SKIP )` from §5.9.14
861//!     segmentation state, computed upstream by the frame parser),
862//!     the spec short-circuits to `skip = 1` with no symbol read;
863//!     otherwise an `S()` symbol is decoded against
864//!     `TileSkipCdf[ctx]` where `ctx = AvailU *
865//!     Skips[MiRow-1][MiCol] + AvailL * Skips[MiRow][MiCol-1]` per
866//!     av1-spec p.378, driven through the walker's `Skips[]` grid
867//!     and [`TileGeometry::is_inside`] for `AvailU` / `AvailL`. The
868//!     §5.11.5 grid-fill (av1-spec p.65 footer) stamps the decoded
869//!     value over the block's `bw4 * bh4` footprint, clipped at the
870//!     frame's `MiRows` / `MiCols` extent. New
871//!     [`PartitionWalker::skips`] accessor returns a row-major view
872//!     of the grid for downstream §5.11.x consumers. Out-of-range
873//!     `mi_row` / `mi_col` / `sub_size` surface as
874//!     [`Error::PartitionWalkOutOfRange`]. Tests cover: seg
875//!     short-circuit no-symbol-read invariant; else-branch S()
876//!     against rigged 2-symbol CDFs (forced 0 and 1); footprint
877//!     grid-stamp on both branches; ctx-0 selection at the frame
878//!     origin (`AvailU = AvailL = false`); ctx-2 selection through
879//!     two prior `Skips=1` neighbours; AvailL-false at the
880//!     left-tile-column boundary; non-zero tile origin clearing
881//!     both `AvailU` / `AvailL`; right-edge `bw4` clip; out-of-range
882//!     guard returns; and the initial all-zero `Skips[]` invariant.
883//!     394 -> 405 tests, zero `#[ignore]`.
884//!
885//!   * **Round 154.** The §5.11.10 `read_skip_mode()` syntax element
886//!     (av1-spec p.67) — the per-block `skip_mode` syntax read.
887//!     Lands as a new [`PartitionWalker::decode_skip_mode`] method
888//!     on the r152 walker, plus a `SkipModes[r][c]` flag grid
889//!     carried alongside the r152 `Skips[]` and the existing
890//!     §6.10.4 `MiSizes[]` grids. The §5.11.10 short-circuit set
891//!     (any-true ⇒ `skip_mode = 0`, no symbol read) is honoured:
892//!     `seg_feature_active(SEG_LVL_SKIP / REF_FRAME / GLOBALMV)`
893//!     collapsed into the caller-provided `seg_skip_mode_off`;
894//!     `!skip_mode_present` via the §5.9.21 frame-header scalar;
895//!     and `Block_Width[MiSize] < 8 || Block_Height[MiSize] < 8`
896//!     derived locally from `sub_size` via the §9.3
897//!     [`cdf::block_width`] / [`cdf::block_height`] tables.
898//!     Otherwise an `S()` symbol is decoded against
899//!     `TileSkipModeCdf[ctx]` with `ctx = AvailU *
900//!     SkipModes[MiRow-1][MiCol] + AvailL *
901//!     SkipModes[MiRow][MiCol-1]` per av1-spec p.378, routed
902//!     through the existing [`skip_mode_ctx`] helper. The §5.11.5
903//!     grid-fill stamps the value over the block's `bw4 * bh4`
904//!     footprint, clipped at the frame's `MiRows` / `MiCols`
905//!     extent. New [`PartitionWalker::skip_modes`] accessor
906//!     returns a row-major view. `skip_mode` is the inter-frame
907//!     compound-reference shortcut read in §5.11.18
908//!     `inter_frame_mode_info` before the rest of the inter
909//!     mode decode (intra-only frames never call this). Tests
910//!     cover: seg short-circuit; `skip_mode_present` false
911//!     short-circuit; both Block_Width-and-Block_Height < 8
912//!     short-circuits via BLOCK_4X8 and BLOCK_8X4; else-branch
913//!     S() against rigged 2-symbol CDFs (forced 0 and 1);
914//!     footprint grid-stamp; ctx-0 selection at the frame
915//!     origin; ctx-1 single-neighbour and ctx-2 both-neighbour
916//!     selection; non-zero tile origin clearing AvailU / AvailL;
917//!     right-edge `bw4` clip; out-of-range guard returns; and
918//!     the initial all-zero `SkipModes[]` invariant. 405 -> 417
919//!     tests, zero `#[ignore]`.
920//!
921//!   * **Round 155.** The §5.11.12 `read_delta_qindex()` syntax
922//!     element (av1-spec p.67) — the per-superblock quantiser
923//!     index delta read. Lands as a new
924//!     [`PartitionWalker::decode_delta_qindex`] method on the r154
925//!     walker, plus a `CurrentQIndex` scalar tracked across calls
926//!     via [`PartitionWalker::current_q_index`] /
927//!     [`PartitionWalker::set_current_q_index`]. Honours the
928//!     §5.11.12 superblock-skip short-circuit (`MiSize == sbSize
929//!     && skip` ⇒ no symbol read; `sbSize` derived from the
930//!     §5.5.1 `use_128x128_superblock` flag) and the outer
931//!     `ReadDeltas` (§6.10.4) gate. Otherwise an `S()` symbol is
932//!     decoded against `TileDeltaQCdf` (a single-row §8.3.2 CDF,
933//!     no context index, length `DELTA_Q_SMALL + 2 = 5`); a
934//!     decoded value of `DELTA_Q_SMALL = 3` triggers the §5.11.12
935//!     escape ladder (`delta_q_rem_bits` `L(3)` + post-increment +
936//!     `delta_q_abs_bits` `L(rem_bits + 1)`), reconstructing the
937//!     absolute value via `delta_q_abs = delta_q_abs_bits + (1 <<
938//!     n) + 1` over the extended range `0..=2 ∪ 3..=511`. Non-zero
939//!     `delta_q_abs` reads `delta_q_sign_bit` `L(1)` and applies the
940//!     spec's `CurrentQIndex = Clip3(1, 255, CurrentQIndex +
941//!     (reducedDeltaQIndex << delta_q_res))` update. New constant
942//!     [`cdf::DELTA_Q_SMALL`] (= 3) plus new table
943//!     [`cdf::DEFAULT_DELTA_Q_CDF`] transcribed verbatim from §9.4
944//!     p.431 (`[28160, 32120, 32677, 32768, 0]`); new field
945//!     [`cdf::TileCdfContext::delta_q`] + accessor
946//!     [`cdf::TileCdfContext::delta_q_cdf`]. Tests cover: default
947//!     CDF literal match; init-from-defaults invariant; sb-skip
948//!     short-circuit for both `use_128x128_superblock` values;
949//!     ReadDeltas false short-circuit; zero `delta_q_abs` no-update;
950//!     literal-positive paths with and without shift; Clip3
951//!     lower-bound via hostile seed; Clip3 upper-bound;
952//!     DELTA_Q_SMALL escape ladder minimum value; escape ladder
953//!     stays in `Clip3(1, 255)` range; cross-call accumulation;
954//!     fresh-walker initial `CurrentQIndex = 0`; out-of-range
955//!     guard; arithmetic decoder zero-byte sign-bit observation.
956//!     417 -> 433 tests, zero `#[ignore]`.
957//!
958//!   * **Round 156.** The §5.11.13 `read_delta_lf()` syntax element
959//!     (av1-spec p.68) — the per-superblock loop-filter delta read,
960//!     structurally parallel to §5.11.12 but iterating
961//!     `frameLfCount` times over a four-slot `DeltaLF[ i ]`
962//!     accumulator with the `delta_lf_multi` flag selecting between
963//!     the §8.3.2 single-LF (`TileDeltaLFCdf`) and per-edge multi-LF
964//!     (`TileDeltaLFMultiCdf[ i ]`) cdf branches. Lands as a new
965//!     [`PartitionWalker::decode_delta_lf`] method plus a
966//!     `current_delta_lf: [i32; FRAME_LF_COUNT]` accumulator on the
967//!     walker (accessors [`PartitionWalker::current_delta_lf`] and
968//!     [`PartitionWalker::reset_current_delta_lf`] for the §5.11.2
969//!     tile-entry reset). Honours the §5.11.13 superblock-skip
970//!     short-circuit identically to §5.11.12, plus the
971//!     `ReadDeltas && delta_lf_present` outer gate (two AND-ed
972//!     flags). When the gate passes, `frameLfCount` is derived
973//!     locally: `delta_lf_multi == 0` ⇒ 1; `delta_lf_multi == 1 &&
974//!     mono_chrome` ⇒ `FRAME_LF_COUNT - 2 = 2`; otherwise
975//!     `FRAME_LF_COUNT = 4`. Each iteration reads `delta_lf_abs`
976//!     `S()` against the branch-selected CDF, then either the
977//!     literal value or the §5.11.13 escape ladder
978//!     (`delta_lf_rem_bits` `L(3)` + post-increment +
979//!     `delta_lf_abs_bits` `L(rem_bits + 1)` ⇒ `deltaLfAbs =
980//!     abs_bits + (1 << n) + 1`), then for non-zero magnitudes
981//!     `delta_lf_sign_bit` `L(1)` followed by the
982//!     `DeltaLF[ i ] = Clip3(-MAX_LOOP_FILTER, MAX_LOOP_FILTER,
983//!     DeltaLF[ i ] + (reducedDeltaLfLevel << delta_lf_res))`
984//!     update. New constants [`cdf::DELTA_LF_SMALL`] (= 3),
985//!     [`cdf::FRAME_LF_COUNT`] (= 4), and
986//!     [`cdf::MAX_LOOP_FILTER`] (= 63 as `i32` — distinct from the
987//!     pre-existing `uncompressed_header_tail::MAX_LOOP_FILTER`
988//!     `i16` twin used by §5.9.11). New table
989//!     [`cdf::DEFAULT_DELTA_LF_CDF`] transcribed verbatim from §9.4
990//!     p.431 (`[28160, 32120, 32677, 32768, 0]`, equal to
991//!     `DEFAULT_DELTA_Q_CDF` per the spec listing — preserved as
992//!     two independent constants so adaptation drift on one does
993//!     not leak through the other). New fields
994//!     [`cdf::TileCdfContext::delta_lf`] +
995//!     [`cdf::TileCdfContext::delta_lf_multi`] with accessors
996//!     [`cdf::TileCdfContext::delta_lf_cdf`] /
997//!     [`cdf::TileCdfContext::delta_lf_multi_cdf`]. 17 new cdf-module
998//!     tests (433 -> 450): default-CDF literal match (incl.
999//!     §9.4 equality with `DEFAULT_DELTA_Q_CDF`); init-from-defaults
1000//!     invariant for both single-LF and all four multi-LF rows;
1001//!     sb-skip short-circuit (64x64 and 128x128); `ReadDeltas`
1002//!     false short-circuit; `delta_lf_present` false short-circuit;
1003//!     single-LF branch writes only `DeltaLF[0]`; multi-LF colour
1004//!     branch writes all four slots; multi-LF monochrome branch
1005//!     writes only the two Y slots; zero-`delta_lf_abs` no-update;
1006//!     literal-positive with shift; Clip3 upper-bound at
1007//!     `MAX_LOOP_FILTER = 63`; Clip3 lower-bound via hostile seed;
1008//!     `DELTA_LF_SMALL` escape ladder minimum value;
1009//!     cross-call accumulation; fresh-walker initial accumulator
1010//!     all-zero + `reset_current_delta_lf` round-trip;
1011//!     out-of-range guard. `decode_av1` / `encode_av1` continue to
1012//!     return `Error::NotImplemented`.
1013//!
1014//!   * **Round 157.** The §5.11.56 `read_cdef()` syntax element
1015//!     (av1-spec p.104) — the per-leaf CDEF-index read, plus the
1016//!     §5.11.55 `clear_cdef()` per-superblock sentinel reset. Lands
1017//!     as new [`PartitionWalker::decode_cdef`] +
1018//!     [`PartitionWalker::clear_cdef`] methods on the r156 walker,
1019//!     plus a `cdef_idx: Vec<i8>` row-major grid sized `MiRows ×
1020//!     MiCols` with [`PartitionWalker::cdef_idx`] read accessor. CDEF
1021//!     operates on 64×64 anchor cells, so the walker masks the leaf
1022//!     `(MiRow, MiCol)` to the anchor at `(MiRow & cdefMask4, MiCol &
1023//!     cdefMask4)` (`cdefMask4 = ~(cdefSize4 - 1)`, `cdefSize4 =
1024//!     Num_4x4_Blocks_Wide[ BLOCK_64X64 ] = 16`) and uses the
1025//!     anchor's `-1` sentinel to decide whether the first leaf in
1026//!     this anchor should read an `L(cdef_bits)` literal (`cdef_bits`
1027//!     in `0..=3` per §5.9.19 `f(2)`). When the literal is read, the
1028//!     grid-fill loop stamps the value across the leaf's
1029//!     `(w4, h4)` footprint at the `cdefSize4 = 16` stride so super-64
1030//!     blocks (`BLOCK_128X128`) reach all four anchor cells while
1031//!     sub-64 blocks touch only their containing anchor. Subsequent
1032//!     leaves in the same 64×64 anchor short-circuit (no read; the
1033//!     anchor already holds the value). The §5.11.56 short-circuit
1034//!     set is honoured: `skip || CodedLossless || !enable_cdef ||
1035//!     allow_intrabc` ⇒ no read, anchor sentinel/value returned
1036//!     unchanged. `clear_cdef( r, c, use_128x128_superblock )` —
1037//!     called by the §5.11.2 tile walk before each superblock —
1038//!     stamps `-1` at the one (64×64 superblocks) or four (128×128
1039//!     superblocks) anchor cells; out-of-grid anchors are silently
1040//!     skipped (the bottom/right superblock can straddle the frame
1041//!     edge). 18 new cdf-module tests (450 → 468): fresh-walker
1042//!     all-`-1` invariant; `clear_cdef` 64x64 single-anchor stamp;
1043//!     `clear_cdef` 128x128 four-anchor stamp; `clear_cdef`
1044//!     out-of-grid skip; each of the four `skip` / `CodedLossless`
1045//!     / `!enable_cdef` / `allow_intrabc` short-circuit gates;
1046//!     first-leaf-reads-literal-and-stamps-anchor; second-leaf-in-
1047//!     anchor-no-read; `cdef_bits == 0` zero-bit stamp; `cdef_bits ==
1048//!     3` upper-bound; anchor-mask routes (10, 13) ⇒ (0, 0);
1049//!     BLOCK_128X128 stamps all four anchors; grid-fill clips at
1050//!     frame edge; short-circuit returns prior stamp; `clear_cdef`
1051//!     after stamp resets anchor; out-of-range guard (4-way:
1052//!     `mi_row` / `mi_col` / `sub_size` / `cdef_bits > 3`).
1053//!     `decode_av1` / `encode_av1` continue to return
1054//!     `Error::NotImplemented`.
1055//!
1056//!   * **Round 158.** The §5.11.20 `read_is_inter()` syntax element
1057//!     (av1-spec p.71-72) — the per-block intra/inter classifier read
1058//!     inside §5.11.18 `inter_frame_mode_info` (after
1059//!     `inter_segment_id` / `read_skip` / `read_cdef` /
1060//!     `read_delta_qindex` / `read_delta_lf`) that dispatches
1061//!     between §5.11.22 `intra_block_mode_info` and §5.11.23
1062//!     `inter_block_mode_info`. Lands as a new
1063//!     [`PartitionWalker::decode_is_inter`] method on the r157
1064//!     walker, plus an `IsInters[r][c]` flag grid carried alongside
1065//!     the r157 `cdef_idx[]`, r154 `SkipModes[]`, r152 `Skips[]`,
1066//!     and the existing §6.10.4 `MiSizes[]` grids
1067//!     (`IsInters[ r + y ][ c + x ] = is_inter` per the §5.11.5
1068//!     footer at av1-spec p.65). All four arms of the §5.11.20
1069//!     dispatch are honoured in spec order (first match fires, no
1070//!     read on the short-circuit arms): Arm 1 — `skip_mode == 1`
1071//!     forces `is_inter = 1`; Arm 2 —
1072//!     `seg_feature_active(SEG_LVL_REF_FRAME)` routes through the
1073//!     caller-pre-computed `FeatureData[segment_id][SEG_LVL_REF_FRAME]
1074//!     != INTRA_FRAME` boolean (the walker stays
1075//!     segmentation-state-free, identical to r154's
1076//!     `seg_skip_mode_off` pattern); Arm 3 —
1077//!     `seg_feature_active(SEG_LVL_GLOBALMV)` forces `is_inter = 1`;
1078//!     Arm 4 — `S()` symbol read against `TileIsInterCdf[ctx]` with
1079//!     `ctx` from the existing [`is_inter_ctx`] helper. The §8.3.2
1080//!     ctx samples neighbour intra-ness from the complement of the
1081//!     walker's `IsInters[]` grid (`intra = !is_inter`), with an
1082//!     unavailable neighbour treated as intra per §5.11.18
1083//!     (`LeftRefFrame[0] = AvailL ? RefFrames[..][0] : INTRA_FRAME`
1084//!     ⇒ `None` to [`is_inter_ctx`]). The §5.11.5 grid-fill stamps
1085//!     the value over the block's `bw4 * bh4` footprint, clipped at
1086//!     the frame's `MiRows` / `MiCols` extent. New
1087//!     [`PartitionWalker::is_inters`] accessor returns a row-major
1088//!     view. 15 new cdf-module tests (468 → 483): fresh-walker grid
1089//!     all-zero; Arm 1 skip_mode short-circuit (position-invariant
1090//!     on a hostile `0xFF` buffer); Arm 2 routing to intra and to
1091//!     inter (both position-invariant); Arm 3 globalmv short-circuit;
1092//!     Arm 1 takes precedence over Arm 2 / Arm 3; Arm 2 takes
1093//!     precedence over Arm 3; else-branch S() returning symbol 0 / 1
1094//!     on rigged binary CDF rows (symbol-1 verifies the footprint
1095//!     grid-stamp); ctx-0 / ctx-1 / ctx-2 / ctx-3 selection through
1096//!     intra/inter seed combinations and a `mi_col_start = 4` tile
1097//!     origin; bottom-right edge clip on `BLOCK_16X16 @ (2, 2)` in
1098//!     a 4×4 frame; three-way out-of-range guard ⇒
1099//!     `PartitionWalkOutOfRange`. `decode_av1` / `encode_av1`
1100//!     continue to return `Error::NotImplemented`.
1101//!
1102//!   * **Round 159.** The §5.11.9 `read_segment_id()` syntax element
1103//!     (av1-spec p.66) — the per-block segment-id reader called
1104//!     inside §5.11.8 `intra_segment_id` and §5.11.19
1105//!     `inter_segment_id` whenever `segmentation_enabled`. Lands as
1106//!     a new [`PartitionWalker::decode_segment_id`] method on the
1107//!     r158 walker, plus a `SegmentIds[r][c]` grid carried alongside
1108//!     the r158 `IsInters[]`, r156 `cdef_idx[]`, r154 `SkipModes[]`,
1109//!     r152 `Skips[]`, and the existing §6.10.4 `MiSizes[]` grids
1110//!     (`SegmentIds[ r + y ][ c + x ] = segment_id` per the §5.11.5
1111//!     grid-fill footer). The grid is pre-filled with the §5.11.9
1112//!     `-1` sentinel; cells inside a decoded block's `bh4 * bw4`
1113//!     footprint then carry `segment_id` in `0..MAX_SEGMENTS = 0..8`.
1114//!     The §5.11.9 neighbour cascade is honoured exactly as
1115//!     spelled out: `prevUL` requires both `AvailU` AND `AvailL`;
1116//!     `prevU` and `prevL` each gate on their own edge; out-of-grid
1117//!     neighbours fall through to `-1`. The four-arm `pred`
1118//!     derivation (`prevU == -1` ⇒ `prevL / 0`; `prevL == -1` ⇒
1119//!     `prevU`; `prevUL == prevU` ⇒ `prevU`; else `prevL`) is
1120//!     preserved verbatim. The §5.11.9 dispatch distinguishes two
1121//!     paths: `skip != 0` ⇒ `segment_id = pred` (zero bits read);
1122//!     else `diff S()` against `TileSegmentIdCdf[ctx]` (ctx from
1123//!     the existing [`segment_id_ctx`] helper) then
1124//!     `segment_id = neg_deinterleave(diff, pred, last_active_seg_id + 1)`.
1125//!     The walker stays segmentation-state-free: the caller passes
1126//!     `last_active_seg_id` (the §5.9.14 trailing derivation) and
1127//!     the `skip` value the §5.11.11 `decode_skip` just returned.
1128//!     New public module-level [`neg_deinterleave`] helper
1129//!     transcribes the §5.11.9 bijection. New
1130//!     [`PartitionWalker::segment_ids`] accessor returns a row-major
1131//!     view. 11 new cdf-module tests (483 → 494): fresh-walker grid
1132//!     all `-1`; skip short-circuit at frame origin writes
1133//!     `segment_id = pred = 0` (no `S()` bit consumed on a hostile
1134//!     `0xFF` byte buffer); skip inherits `prev_u` when `prev_l` is
1135//!     unavailable; non-skip path with `pred = 0` returns `diff`
1136//!     unchanged; direct `neg_deinterleave` table exercises for both
1137//!     `2 * ref < max` and `2 * ref >= max` branches plus edge cases
1138//!     (`ref == 0` identity, `ref == max - 1` inverted, smallest
1139//!     non-trivial alphabet `max = 2`); ctx-0 origin selection;
1140//!     ctx-2 all-neighbours-match selection through three
1141//!     walker-stamped seeds; bottom-right edge clip on
1142//!     `BLOCK_16X16 @ (2, 2)` in a 4×4 frame; four-way out-of-range
1143//!     guard. `decode_av1` / `encode_av1` continue to return
1144//!     `Error::NotImplemented`.
1145//!
1146//!   * **Round 160.** The §5.11.8 `intra_segment_id()` syntax
1147//!     element (av1-spec p.66) — the intra-frame variant of the
1148//!     per-block segment-id read, called from §5.11.7
1149//!     `intra_frame_mode_info` on both the `SegIdPreSkip` and
1150//!     `!SegIdPreSkip` arms. Lands as a new
1151//!     [`PartitionWalker::decode_intra_segment_id`] method that
1152//!     dispatches on the caller-passed `segmentation_enabled` bit:
1153//!     when set, descends into r159
1154//!     [`PartitionWalker::decode_segment_id`] (which does the
1155//!     §5.11.9 neighbour cascade + skip / non-skip dispatch + grid
1156//!     fill); when clear, stamps `segment_id = 0` over the leaf's
1157//!     `bh4 * bw4` footprint without reading any bits. Both arms
1158//!     then resolve the §5.11.8 `Lossless = LosslessArray[
1159//!     segment_id ]` lookup via a caller-supplied
1160//!     `lossless_array: &[bool; MAX_SEGMENTS]` (the §6.8.2
1161//!     per-segment table the frame-header walk computes from
1162//!     `qindex` + `DeltaQ?Dc` + `DeltaQ?Ac`). Returns
1163//!     `(segment_id, lossless)`. The walker stays
1164//!     segmentation-state-free: callers pass `segmentation_enabled`,
1165//!     `last_active_seg_id`, and `lossless_array` per-call (matching
1166//!     the r159 pattern). Range guards (out-of-range `sub_size`,
1167//!     `mi_row` / `mi_col` past the frame's mi extent,
1168//!     `last_active_seg_id >= MAX_SEGMENTS`) fire on both arms so
1169//!     the no-symbol path is total over the same input space as the
1170//!     bitstream-reading path. 7 new cdf-module tests (494 → 501):
1171//!     `segmentation_enabled = false` no-read on a hostile `0xFF`
1172//!     buffer with `lossless_array[0] = true` and `= false` arms;
1173//!     `segmentation_enabled = true, skip = 1` at frame origin
1174//!     (pred = 0, no `S()` consumed); `segmentation_enabled = true,
1175//!     skip = 0` reading `diff = 3` on a rigged CDF and looking up
1176//!     `lossless_array[3]`; per-segment Lossless indexing (rig
1177//!     `diff = 5`, set `lossless_array[5] = false` while every
1178//!     other slot is `true`, expect `Lossless = false`);
1179//!     bottom-right edge-clip on `BLOCK_16X16 @ (2, 2)` in a 4×4
1180//!     frame on the `!segmentation_enabled` arm; five-way
1181//!     out-of-range guard covering both arms. `decode_av1` /
1182//!     `encode_av1` continue to return `Error::NotImplemented`.
1183//!
1184//!   * **Round 161.** The §5.11.7 `intra_frame_mode_info()`
1185//!     **prefix dispatcher** (av1-spec p.64) — the per-block top-level
1186//!     entry-point that composes the §5.11.7 first 11 lines:
1187//!     `skip = 0`; conditional pre-skip `intra_segment_id()`;
1188//!     `skip_mode = 0`; `read_skip()`; conditional post-skip
1189//!     `intra_segment_id()`; `read_cdef()`; `read_delta_qindex()`;
1190//!     `read_delta_lf()`; the fixed `ReadDeltas = 0` / `RefFrame[0]
1191//!     = INTRA_FRAME` / `RefFrame[1] = NONE` assignments. Lands as
1192//!     a new [`PartitionWalker::decode_intra_frame_mode_info_prefix`]
1193//!     method on the r160 walker, returning the new public
1194//!     [`cdf::IntraFrameModeInfoPrefix`] struct carrying every
1195//!     post-call observable (`skip`, `skip_mode`, `segment_id`,
1196//!     `lossless`, `cdef_idx`, `current_q_index`,
1197//!     `current_delta_lf`, `ref_frame`). The §5.11.7 `SegIdPreSkip`
1198//!     conditional routes the §5.11.8 call before or after the
1199//!     §5.11.11 `read_skip()` per the caller-passed
1200//!     `seg_id_pre_skip` boolean (the §5.9.14 trailing
1201//!     derivation). `skip_mode` is fixed at `0` because the
1202//!     intra-frame walk never calls `decode_skip_mode` (§5.11.10
1203//!     short-circuits on `!skip_mode_present` for intra-only frames
1204//!     per §5.9.21). The §6.10.4 `ReadDeltas = 0` assignment is
1205//!     left to the caller (the walker remains stateless about
1206//!     per-superblock first-block detection), matching the
1207//!     §6.10.4 pattern existing
1208//!     [`PartitionWalker::decode_delta_qindex`] /
1209//!     [`PartitionWalker::decode_delta_lf`] call sites already
1210//!     use. Range guards (out-of-range `sub_size`, `mi_row` /
1211//!     `mi_col`, `last_active_seg_id >= MAX_SEGMENTS`, `cdef_bits >
1212//!     3`) fire on the dispatcher level before any inner read so a
1213//!     caller bug never produces a partial-read. 8 new cdf-module
1214//!     tests (501 → 509): minimum-bit path (one `S()` consumed for
1215//!     `read_skip`); `SegIdPreSkip = true` arm reading
1216//!     `segment_id` first then `skip`; `SegIdPreSkip = false` arm
1217//!     post-skip with `skip = 1` triggering the §5.11.9
1218//!     short-circuit; seg-skip-active forcing `skip = 1` with zero
1219//!     bits consumed on a hostile `0xFF` buffer; fixed
1220//!     `ref_frame = [INTRA_FRAME, NONE]`; `read_deltas` true
1221//!     wiring through to both `delta_q` and `delta_lf` reads;
1222//!     five-way out-of-range guard; `skip_mode` always `0` on both
1223//!     pre-skip arms (verifies `SkipModes[]` grid untouched). The
1224//!     §5.11.7 follow-on body (`use_intrabc` arm + `intra_block_mode_info`
1225//!     composite) and the §5.11.18 `inter_frame_mode_info` /
1226//!     §5.11.19 `inter_segment_id` two-call protocol remain the
1227//!     next round's targets. `decode_av1` / `encode_av1` continue
1228//!     to return `Error::NotImplemented`.
1229//!
1230//!   * **Round 162.** The §5.11.19 `inter_segment_id( preSkip )`
1231//!     syntax element (av1-spec p.71) — the inter-frame variant of
1232//!     the per-block segment-id read, called twice per block from
1233//!     §5.11.18 (once before §5.11.11 `read_skip()` with
1234//!     `preSkip = 1` and once after with `preSkip = 0`). Lands as
1235//!     a new [`PartitionWalker::decode_inter_segment_id`] method.
1236//!     New `SEGMENT_ID_PREDICTED_CONTEXTS = 3` (§9.3) constant and
1237//!     [`cdf::DEFAULT_SEGMENT_ID_PREDICTED_CDF`] table verbatim from
1238//!     §9.4 (av1-spec p.442 — three uniform `[128 * 128, 32768, 0]`
1239//!     rows for the binary `seg_id_predicted` symbol). New
1240//!     [`cdf::TileCdfContext::segment_id_predicted`] field
1241//!     initialised from `DEFAULT_SEGMENT_ID_PREDICTED_CDF` plus the
1242//!     [`cdf::TileCdfContext::segment_id_predicted_cdf`] selector
1243//!     implementing the §8.3.2 `TileSegmentIdPredictedCdf[ ctx ]`
1244//!     index. New persistent `above_seg_pred_context` (length
1245//!     `mi_cols`) and `left_seg_pred_context` (length `mi_rows`)
1246//!     buffers on `PartitionWalker` per the §8.3.1 tile-entry
1247//!     initialisation; the §8.3.2 ctx walk reads `LeftSegPredContext[
1248//!     MiRow ] + AboveSegPredContext[ MiCol ]` (each `0..=1`; sum
1249//!     `0..=2 < SEGMENT_ID_PREDICTED_CONTEXTS`).
1250//!     [`PartitionWalker::above_seg_pred_context`] /
1251//!     [`PartitionWalker::left_seg_pred_context`] accessors surface
1252//!     the arrays. The dispatcher routes the full §5.11.19 cascade
1253//!     exactly: outer `!segmentation_enabled` collapses to
1254//!     `segment_id = 0`; inner `!segmentation_update_map` adopts
1255//!     `predictedSegmentId`; `pre_skip && !SegIdPreSkip` early-exit
1256//!     returns `segment_id = 0`; the post-skip `skip != 0` arm
1257//!     zeroes the context arrays then descends into `decode_segment_id`
1258//!     (the §5.11.9 skip short-circuit fires inside); the
1259//!     `segmentation_temporal_update == 1` arm reads
1260//!     `seg_id_predicted`, branches to `predictedSegmentId` adopt
1261//!     or `read_segment_id()`, and stamps the context arrays with
1262//!     the just-read flag; the `temporal_update == 0` fall-through
1263//!     reads `read_segment_id()` without touching the context arrays
1264//!     (per spec). `predicted_segment_id` (§5.11.21 `get_segment_id()`)
1265//!     is caller-supplied from the §6.10 reference-frame walk so
1266//!     the walker stays inter-frame-state-free. Range guards
1267//!     (out-of-range `sub_size`, `mi_row`/`mi_col` past extent,
1268//!     `last_active_seg_id >= MAX_SEGMENTS`, and the new
1269//!     `predicted_segment_id > last_active_seg_id` invariant) fire
1270//!     up-front on every arm. 11 new cdf-module tests (509 → 520):
1271//!     fresh-walker context-array zeroing; `!segmentation_enabled`
1272//!     no-read on both pre/post-skip arms; `!segmentation_update_map`
1273//!     predicted-id adoption; `pre_skip && !SegIdPreSkip` early-exit;
1274//!     post-skip + `skip != 0` zeroing context arrays then descending
1275//!     into the §5.11.9 short-circuit (poisoned context arrays prove
1276//!     the spec write fires); `temporal_update == 1` + rigged
1277//!     `seg_id_predicted = 1` adopting predicted id and stamping
1278//!     context to `1`; `temporal_update == 1` + rigged
1279//!     `seg_id_predicted = 0` descending into `decode_segment_id`
1280//!     and stamping context to `0`; `temporal_update == 0`
1281//!     fall-through leaving context untouched; five-way out-of-range
1282//!     guard; `Default_Segment_Id_Predicted_Cdf` layout; the
1283//!     `segment_id_predicted_cdf` accessor round-trip. The §5.11.18
1284//!     `inter_frame_mode_info()` top-level dispatcher remains the
1285//!     next round's architectural payoff. `decode_av1` /
1286//!     `encode_av1` continue to return `Error::NotImplemented`.
1287//!
1288//!   * **Round 163.** The §5.11.21 `get_segment_id()` pure-helper
1289//!     function (av1-spec p.72) — the inter-frame per-block segment-id
1290//!     **prediction** lookup that scans the previous frame's
1291//!     `PrevSegmentIds[][]` over the on-screen window covered by the
1292//!     current block and returns the smallest id found. Lands as a
1293//!     new free function [`cdf::get_segment_id`] (re-exported at the
1294//!     crate root) that takes the previous-frame segmentation surface
1295//!     as a row-major `&[i32]` slice plus its (`prev_mi_rows`,
1296//!     `prev_mi_cols`) extent, the current frame's mi-extent
1297//!     (`mi_rows`, `mi_cols`) and anchor (`mi_row`, `mi_col`), and the
1298//!     block's `sub_size` (§3 `BLOCK_*` ordinal). Returns
1299//!     `Some(seg)` with the §5.11.21 `Min` reduction result over
1300//!     `xMis = Min(MiCols - MiCol, bw4)` × `yMis = Min(MiRows - MiRow,
1301//!     bh4)` cells; `seg` is in `-1..=7` (the `-1` sentinel surfaces
1302//!     when an unwritten previous-frame cell falls inside the window,
1303//!     letting callers detect a malformed reference surface via the
1304//!     existing §5.11.19 `predicted_segment_id > last_active_seg_id`
1305//!     range guard). Returns `None` for caller-bug arguments
1306//!     (out-of-range `sub_size`, anchor outside the current frame,
1307//!     previous-frame extent smaller than the current frame's, or
1308//!     `prev_segment_ids` length not matching `prev_mi_rows *
1309//!     prev_mi_cols`). The function is **pure** (no walker state, no
1310//!     bitreader, no CDF) and complements the r162
1311//!     [`cdf::PartitionWalker::decode_inter_segment_id`] caller —
1312//!     which takes a pre-computed `predicted_segment_id: u8` so the
1313//!     walker can stay inter-frame-state-free — by giving the §6.10
1314//!     reference-frame walk a verbatim spec-shaped routine to compute
1315//!     that argument from `PrevSegmentIds[]`. 12 new cdf-module
1316//!     tests (520 → 532): uniform-0 / uniform-7 reductions over
1317//!     several block sizes; explicit Min-over-2x2-window cells with
1318//!     out-of-window decoy values that must not contribute; frame-edge
1319//!     `xMis`/`yMis` clipping on a `BLOCK_16X16` anchored at the
1320//!     bottom-right of a 4x4 mi-grid; `-1` sentinel round-trip; a
1321//!     wider-than-current previous frame exercising the
1322//!     `prev_mi_cols` row stride; single-cell `BLOCK_4X4` covering
1323//!     exactly `prev[MiRow][MiCol]` with a neighbour-cell decoy;
1324//!     out-of-range guards for invalid `sub_size`, anchor past frame
1325//!     extent, previous-frame extent smaller than current frame's,
1326//!     and length / shape mismatch; an end-to-end composition test
1327//!     feeding `get_segment_id`'s result into
1328//!     `decode_inter_segment_id`'s no-read
1329//!     `!segmentation_update_map` arm and verifying the predicted id
1330//!     is adopted with zero bit reads on a hostile `0xFF` buffer.
1331//!     The §5.11.18 `inter_frame_mode_info()` top-level dispatcher,
1332//!     §5.11.7 `use_intrabc` arm, and §5.11.22 `intra_block_mode_info`
1333//!     composite remain the next round's targets. `decode_av1` /
1334//!     `encode_av1` continue to return `Error::NotImplemented`.
1335//!
1336//!   * **Round 168.** §5.11.17 `read_var_tx_size()` (av1-spec p.70) +
1337//!     §5.11.18 `inter_frame_mode_info()` (av1-spec p.71) — the two
1338//!     missing inter-arm composites that bound the §5.11.5 walker's
1339//!     inter side. The §5.11.17 reader is exposed as
1340//!     [`cdf::PartitionWalker::read_var_tx_size`] (callable
1341//!     standalone) and wired into the §5.11.16 inter-arm so
1342//!     [`cdf::PartitionWalker::read_block_tx_size`] no longer
1343//!     surfaces [`Error::ReadVarTxSizeUnsupported`] on the
1344//!     `TX_MODE_SELECT && is_inter && !skip && !Lossless` arm — the
1345//!     recursion stamps `InterTxSizes[]` per terminal-else leaf and
1346//!     the outer §5.11.5 footer stamps `TxSizes[]` over the full
1347//!     block footprint. The §8.3.2 `txfm_split` ctx selector inlines
1348//!     the spec's `get_above_tx_width` / `get_left_tx_height`
1349//!     helpers as private [`cdf::PartitionWalker`] methods against
1350//!     the walker's `Skips[]` / `IsInters[]` / `MiSizes[]` /
1351//!     `InterTxSizes[]` grids, and routes the
1352//!     `(above, left, txSzSqrUp, maxTxSz)` derivation through the
1353//!     existing [`cdf::txfm_split_ctx`] helper. New free function
1354//!     [`cdf::find_tx_size`] (§5.11.36 helper, re-exported) supports
1355//!     the `maxTxSz = find_tx_size(size, size)` step of the ctx
1356//!     formula.
1357//!
1358//!     The §5.11.18 reader is exposed as
1359//!     [`cdf::PartitionWalker::decode_inter_frame_mode_info`]
1360//!     composing every leaf already wired through the walker:
1361//!     [`cdf::PartitionWalker::decode_inter_segment_id`] (pre- and
1362//!     post-skip arms), [`cdf::PartitionWalker::decode_skip_mode`],
1363//!     [`cdf::PartitionWalker::decode_skip`] (gated by
1364//!     `skip_mode == 0`), [`cdf::PartitionWalker::decode_cdef`],
1365//!     [`cdf::PartitionWalker::decode_delta_qindex`],
1366//!     [`cdf::PartitionWalker::decode_delta_lf`], and
1367//!     [`cdf::PartitionWalker::decode_is_inter`]. The terminal
1368//!     `if (is_inter)` dispatch short-circuits at two new `Error`
1369//!     variants: [`Error::InterBlockModeInfoUnsupported`] (§5.11.23
1370//!     `inter_block_mode_info()` — the next-round target for the
1371//!     MV stack / ref-frame readers) and
1372//!     [`Error::IntraBlockModeInfoUnsupported`] (§5.11.22
1373//!     `intra_block_mode_info()` — the next-round target for the
1374//!     per-block intra angle / UV mode readers). New
1375//!     [`cdf::DecodedInterFrameModeInfo`] aggregate carries every
1376//!     §5.11.18 derived value.
1377//!
1378//!     The §5.11.5 [`cdf::PartitionWalker::decode_block_syntax`]
1379//!     walker is unchanged on the `frame_is_intra = false` arm — it
1380//!     still surfaces [`Error::DecodeBlockInterFrameUnsupported`]
1381//!     (the umbrella stub) because the §5.11.18 reader needs
1382//!     additional caller state (`segmentation_update_map` /
1383//!     `segmentation_temporal_update` / `predicted_segment_id` /
1384//!     `seg_*_active` overrides / `skip_mode_present`) the §5.11.5
1385//!     driver doesn't yet thread through. Direct callers of
1386//!     `decode_inter_frame_mode_info` get the full pre-dispatch walk
1387//!     and the §5.11.22 / §5.11.23 distinction.
1388//!
1389//!     11 new integration tests cover the §5.11.17 base case + depth
1390//!     cap + split path + frame-edge clip + caller-bug guards + the
1391//!     wired §5.11.16 inter-arm, plus the §5.11.18 intra / inter
1392//!     stub dispatch + skip-mode-forces-skip + segment-globalmv
1393//!     arm + caller-bug guards + the `DecodedInterFrameModeInfo`
1394//!     public-API smoke. Plus 1 new unit test for `find_tx_size`.
1395//!     `decode_av1` / `encode_av1` continue to return
1396//!     [`Error::NotImplemented`].
1397//!
1398//!   * **Round 167.** The §5.11.16 `read_block_tx_size()` reader
1399//!     (av1-spec p.70) — the per-block transform-size syntax-tree
1400//!     read that r166's §5.11.5 walker hit as the first stub on the
1401//!     intra arm. Lands as a new
1402//!     [`cdf::PartitionWalker::read_block_tx_size`] method
1403//!     (callable standalone) and is wired into the §5.11.5 walker
1404//!     so the walker now reaches
1405//!     [`Error::DecodeBlockComputePredictionUnsupported`] (§5.11.30)
1406//!     instead.
1407//!
1408//!     The reader transcribes the spec body one-to-one. The outer
1409//!     `TX_MODE_SELECT && MiSize > BLOCK_4X4 && is_inter && !skip &&
1410//!     !Lossless` arm routes to §5.11.17 `read_var_tx_size` (the
1411//!     next-arc target — surfaces a new
1412//!     [`Error::ReadVarTxSizeUnsupported`]). The `else` arm inlines
1413//!     §5.11.15 `read_tx_size(!skip || !is_inter)`: a `Lossless`
1414//!     short-circuit forces `TxSize = TX_4X4`; otherwise `TxSize`
1415//!     starts at `Max_Tx_Size_Rect[ MiSize ]` and is further split
1416//!     via `Split_Tx_Size[]` for `tx_depth` iterations when the
1417//!     §5.11.15 `MiSize > BLOCK_4X4 && allowSelect && TxMode ==
1418//!     TX_MODE_SELECT` gate fires. The §8.3.2 `tx_depth` ctx walks
1419//!     the neighbour `IsInters[]` / `MiSizes[]` / `InterTxSizes[]`
1420//!     ladder per `get_above_tx_width` / `get_left_tx_height` and
1421//!     selects the CDF row via `Max_Tx_Depth[ MiSize ]`. The
1422//!     `else`-arm grid-fill stamps both
1423//!     [`cdf::PartitionWalker::inter_tx_sizes`] and the §5.11.5
1424//!     footer's [`cdf::PartitionWalker::tx_sizes`] across the block
1425//!     footprint.
1426//!
1427//!     New spec tables ([`cdf::MAX_TX_SIZE_RECT`] /
1428//!     [`cdf::MAX_TX_DEPTH_TABLE`] / [`cdf::SPLIT_TX_SIZE`] /
1429//!     [`cdf::MAX_VARTX_DEPTH`]) and 14 new rectangular `TX_*`
1430//!     ordinals ([`cdf::TX_4X8`] / ... / [`cdf::TX_64X16`])
1431//!     transcribe av1-spec p.402, p.69, p.404, §3 p.7, and §6.10.16
1432//!     respectively. New [`cdf::PartitionWalker`] grids
1433//!     `tx_sizes` / `inter_tx_sizes` cover §5.11.5 / §5.11.16
1434//!     write semantics. [`cdf::DecodedBlock`] gains a `tx_size`
1435//!     field; [`cdf::PartitionWalker::decode_block_syntax`] gains a
1436//!     `tx_mode_select: bool` parameter (threaded from the
1437//!     §5.9.21 / §6.8.21 frame-header `TxMode` derivation).
1438//!
1439//!     10 new integration tests cover the new reader's spec paths;
1440//!     5 new unit tests verify the spec tables.
1441//!     `decode_av1` / `encode_av1` continue to return
1442//!     [`Error::NotImplemented`].
1443//!
1444//!   * **Round 166.** The §5.11.5 `decode_block()` syntax-walker
1445//!     skeleton (av1-spec p.63-64) — the missing dispatcher that
1446//!     the §5.11.4 partition walker recurses into at every leaf.
1447//!     Lands as a new [`cdf::PartitionWalker::decode_block_syntax`]
1448//!     method that performs the §5.11.5 prologue (`MiRow`, `MiCol`,
1449//!     `MiSize`, `bw4`, `bh4`; the `HasChroma` three-arm dispatch
1450//!     on `bh4 == 1 && subsampling_y && (MiRow & 1) == 0` and
1451//!     `bw4 == 1 && subsampling_x && (MiCol & 1) == 0`; `AvailU`,
1452//!     `AvailL`, `AvailUChroma`, `AvailLChroma` derivation with the
1453//!     spec's chroma fix-up arm) and the §5.11.6 `mode_info()`
1454//!     intra arm composed from r161's
1455//!     [`cdf::PartitionWalker::decode_intra_frame_mode_info_prefix`],
1456//!     r164's [`cdf::PartitionWalker::decode_use_intrabc`], and
1457//!     r165's [`cdf::PartitionWalker::decode_intra_frame_y_mode`].
1458//!     The §5.11.49 `palette_tokens()` call is a no-op on the
1459//!     no-palette path. Short-circuits at the §5.11.16
1460//!     `read_block_tx_size()` call with a new
1461//!     [`Error::DecodeBlockReadBlockTxSizeUnsupported`] — the
1462//!     immediate next-round target.
1463//!
1464//!     Four new [`Error`] variants surface the §5.11.5 next-round
1465//!     boundaries one-to-one:
1466//!     [`Error::DecodeBlockInterFrameUnsupported`] (§5.11.18
1467//!     `inter_frame_mode_info()`, fires on `frame_is_intra = false`
1468//!     with zero bits consumed);
1469//!     [`Error::DecodeBlockReadBlockTxSizeUnsupported`] (§5.11.16,
1470//!     the stub the walker actually reaches);
1471//!     [`Error::DecodeBlockComputePredictionUnsupported`] (§5.11.30,
1472//!     reserved for the round that lands §5.11.16); and
1473//!     [`Error::DecodeBlockResidualUnsupported`] (§5.11.34,
1474//!     reserved for the round that lands §5.11.30).
1475//!
1476//!     New [`cdf::DecodedBlock`] per-block aggregate — publicly
1477//!     constructible — carries the §5.11.5 prologue + §5.11.7
1478//!     mode-info derivations on the no-stub path. Reachable once
1479//!     §5.11.16 lands.
1480//!
1481//!     §5.11.4 partition driver mirror:
1482//!     [`cdf::PartitionWalker::decode_partition_syntax`] walks the
1483//!     same recursion shape as
1484//!     [`cdf::PartitionWalker::decode_partition`] but routes every
1485//!     leaf through `decode_block_syntax` instead of the leaf-only
1486//!     emitter. Stub propagates from the first leaf that fires it.
1487//!
1488//!     10 new integration tests
1489//!     (`tests/decode_block_syntax_walker.rs`) cover the §5.11.5
1490//!     prologue's three-arm `HasChroma` dispatch on `BLOCK_4X4`,
1491//!     the §5.11.6 inter-arm stub, the §5.11.7 `SegIdPreSkip`
1492//!     pre-skip arm reaching the §5.11.16 stub after the composed
1493//!     reads fire in spec order, out-of-range guards, the §5.11.4
1494//!     partition driver's `BLOCK_4X4` short-circuit arm propagating
1495//!     the stub, the §5.11.4 `r >= MiRows` line-1 early return,
1496//!     `DecodedBlock` public-API constructibility, `BLOCK_8X16`
1497//!     grid-fill footprint (bw4 = 2, bh4 = 4), and `BLOCK_16X16`
1498//!     with `cdef_bits = 2` exercising the §5.11.56 literal-bits
1499//!     read.
1500//!
1501//!     The §5.11.7 follow-on `else`-arm elements
1502//!     (`intra_angle_info_y`, `uv_mode`, `read_cfl_alphas`,
1503//!     `intra_angle_info_uv`, `palette_mode_info`,
1504//!     `filter_intra_mode_info`) and the `use_intrabc == 1`
1505//!     MV-stack / assign-mv body remain bounded leaf targets that
1506//!     can be slotted into a future round before or alongside
1507//!     §5.11.16. `decode_av1` / `encode_av1` continue to return
1508//!     [`Error::NotImplemented`].
1509//!
1510//! Tile-group / tile-content decode (the per-tile coefficient,
1511//! motion-vector, and reconstruction passes) remains out of scope, as
1512//! does the §7.20 reference frame update process that would store a
1513//! decoded frame back into [`frame_header::RefInfo`] across frames.
1514//! [`decode_av1`] / [`encode_av1`] continue to return
1515//! [`Error::NotImplemented`].
1516
1517#![warn(missing_debug_implementations)]
1518
1519use oxideav_core::RuntimeContext;
1520
1521pub mod annexb;
1522mod bitreader;
1523pub mod codec_config;
1524// internal — exposed for tests/fuzz; not part of the stable API
1525#[doc(hidden)]
1526pub mod cdef;
1527// internal — exposed for tests/fuzz; not part of the stable API
1528#[doc(hidden)]
1529pub mod cdf;
1530pub mod decoder;
1531pub mod encoder;
1532// internal — exposed for tests/fuzz; not part of the stable API
1533#[doc(hidden)]
1534pub mod film_grain;
1535mod film_grain_tables;
1536// internal — exposed for tests/fuzz; not part of the stable API
1537#[doc(hidden)]
1538pub mod frame_header;
1539// internal — exposed for tests/fuzz; not part of the stable API
1540#[doc(hidden)]
1541pub mod inter_pred;
1542// internal — exposed for tests/fuzz; not part of the stable API
1543#[doc(hidden)]
1544pub mod loop_filter;
1545// internal — exposed for tests/fuzz; not part of the stable API
1546#[doc(hidden)]
1547pub mod loop_restoration;
1548// internal — exposed for tests/fuzz; not part of the stable API
1549#[doc(hidden)]
1550pub mod obu;
1551// internal — exposed for tests/fuzz; not part of the stable API
1552#[doc(hidden)]
1553pub mod qmatrix;
1554pub mod registry;
1555// internal — exposed for tests/fuzz; not part of the stable API
1556#[doc(hidden)]
1557pub mod scan;
1558// internal — exposed for tests/fuzz; not part of the stable API
1559#[doc(hidden)]
1560pub mod sequence_header;
1561// internal — exposed for tests/fuzz; not part of the stable API
1562#[doc(hidden)]
1563pub mod superres;
1564// internal — exposed for tests/fuzz; not part of the stable API
1565#[doc(hidden)]
1566pub mod symbol_decoder;
1567// internal — exposed for tests/fuzz; not part of the stable API
1568#[doc(hidden)]
1569pub mod tile_info;
1570pub mod tile_list;
1571// internal — exposed for tests/fuzz; not part of the stable API
1572#[doc(hidden)]
1573pub mod transform;
1574// internal — exposed for tests/fuzz; not part of the stable API
1575#[doc(hidden)]
1576pub mod uncompressed_header_tail;
1577
1578#[doc(hidden)]
1579pub use cdf::{
1580    block_height, block_width, cfl_alpha_u_ctx, cfl_alpha_v_ctx, coeff_cdf_q_ctx,
1581    compound_mode_ctx, compute_tx_type, find_tx_size, get_br_ctx, get_coeff_base_ctx,
1582    get_coeff_base_eob_ctx, get_palette_color_context, get_segment_id, get_tx_class,
1583    inter_tx_type_set, interintra_ctx, interp_filter_ctx, intra_dir, intra_mode_ctx,
1584    intra_tx_type_set, is_inter_ctx, is_tx_type_in_set, mi_height_log2, mi_width_log2, mv_ctx,
1585    neg_deinterleave, num_4x4_blocks_high, num_4x4_blocks_wide,
1586    palette_color_context_from_neighbors, palette_color_ctx, palette_tokens_args,
1587    palette_tokens_plane, palette_uv_mode_ctx, palette_y_mode_ctx, partition_ctx,
1588    partition_subsize, ref_count_ctx, segment_id_ctx, size_group, skip_ctx, skip_mode_ctx,
1589    split_or_horz_cdf, split_or_vert_cdf, tx_depth_ctx, txfm_split_ctx, DecodedBlock,
1590    DecodedBlockRecord, DecodedInterBlockModeInfo, DecodedInterFrameModeInfo, DecodedPaletteMap,
1591    FindMvStackResult, FrameInterOrderHints, InterFrameContext, InterWalkPixels,
1592    IntraFrameModeInfoPrefix, PaletteColorContext, PalettePlane, PaletteTokensArgs,
1593    PartitionWalker, TileCdfContext, TileDecodeParams, TileGeometry, ADJUSTED_TX_SIZE, ADST_ADST,
1594    ADST_DCT, ADST_FLIPADST, BLOCK_128X128, BLOCK_128X64, BLOCK_16X16, BLOCK_16X32, BLOCK_16X4,
1595    BLOCK_16X64, BLOCK_16X8, BLOCK_32X16, BLOCK_32X32, BLOCK_32X64, BLOCK_32X8, BLOCK_4X16,
1596    BLOCK_4X4, BLOCK_4X8, BLOCK_64X128, BLOCK_64X16, BLOCK_64X32, BLOCK_64X64, BLOCK_8X16,
1597    BLOCK_8X32, BLOCK_8X4, BLOCK_8X8, BLOCK_INVALID, BLOCK_SIZES, BLOCK_SIZE_GROUPS, BR_CDF_SIZE,
1598    BWD_REFS, CFL_ALPHABET_SIZE, CFL_ALPHA_CONTEXTS, CFL_JOINT_SIGNS, CLASS0_SIZE,
1599    COEFF_BASE_CTX_OFFSET, COEFF_BASE_POS_CTX_OFFSET, COEFF_BASE_RANGE, COEFF_CDF_Q_CTXS,
1600    COMPOUND_IDX_CONTEXTS, COMPOUND_MODES, COMPOUND_MODE_CONTEXTS, COMPOUND_MODE_CTX_MAP,
1601    COMPOUND_TYPES, COMP_GROUP_IDX_CONTEXTS, COMP_INTER_CONTEXTS, COMP_NEWMV_CTXS,
1602    COMP_REF_TYPE_CONTEXTS, DCT_ADST, DCT_DCT, DCT_FLIPADST, DC_SIGN_CONTEXTS,
1603    DEFAULT_ANGLE_DELTA_CDF, DEFAULT_CFL_ALPHA_CDF, DEFAULT_CFL_SIGN_CDF, DEFAULT_COEFF_BASE_CDF,
1604    DEFAULT_COEFF_BASE_EOB_CDF, DEFAULT_COEFF_BR_CDF, DEFAULT_COMPOUND_IDX_CDF,
1605    DEFAULT_COMPOUND_MODE_CDF, DEFAULT_COMPOUND_TYPE_CDF, DEFAULT_COMP_BWD_REF_CDF,
1606    DEFAULT_COMP_GROUP_IDX_CDF, DEFAULT_COMP_MODE_CDF, DEFAULT_COMP_REF_CDF,
1607    DEFAULT_COMP_REF_TYPE_CDF, DEFAULT_DC_SIGN_CDF, DEFAULT_DELTA_LF_CDF, DEFAULT_DELTA_Q_CDF,
1608    DEFAULT_DRL_MODE_CDF, DEFAULT_EOB_EXTRA_CDF, DEFAULT_EOB_PT_1024_CDF, DEFAULT_EOB_PT_128_CDF,
1609    DEFAULT_EOB_PT_16_CDF, DEFAULT_EOB_PT_256_CDF, DEFAULT_EOB_PT_32_CDF, DEFAULT_EOB_PT_512_CDF,
1610    DEFAULT_EOB_PT_64_CDF, DEFAULT_FILTER_INTRA_CDF, DEFAULT_FILTER_INTRA_MODE_CDF,
1611    DEFAULT_INTERP_FILTER_CDF, DEFAULT_INTER_INTRA_CDF, DEFAULT_INTER_INTRA_MODE_CDF,
1612    DEFAULT_INTER_TX_TYPE_SET1_CDF, DEFAULT_INTER_TX_TYPE_SET2_CDF, DEFAULT_INTER_TX_TYPE_SET3_CDF,
1613    DEFAULT_INTRABC_CDF, DEFAULT_INTRA_FRAME_Y_MODE_CDF, DEFAULT_INTRA_TX_TYPE_SET1_CDF,
1614    DEFAULT_INTRA_TX_TYPE_SET2_CDF, DEFAULT_IS_INTER_CDF, DEFAULT_MOTION_MODE_CDF,
1615    DEFAULT_MV_BIT_CDF, DEFAULT_MV_CLASS0_BIT_CDF, DEFAULT_MV_CLASS0_FR_CDF,
1616    DEFAULT_MV_CLASS0_HP_CDF, DEFAULT_MV_CLASS_CDF, DEFAULT_MV_FR_CDF, DEFAULT_MV_HP_CDF,
1617    DEFAULT_MV_JOINT_CDF, DEFAULT_MV_SIGN_CDF, DEFAULT_NEW_MV_CDF,
1618    DEFAULT_PALETTE_SIZE_2_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_2_Y_COLOR_CDF,
1619    DEFAULT_PALETTE_SIZE_3_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_3_Y_COLOR_CDF,
1620    DEFAULT_PALETTE_SIZE_4_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_4_Y_COLOR_CDF,
1621    DEFAULT_PALETTE_SIZE_5_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_5_Y_COLOR_CDF,
1622    DEFAULT_PALETTE_SIZE_6_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_6_Y_COLOR_CDF,
1623    DEFAULT_PALETTE_SIZE_7_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_7_Y_COLOR_CDF,
1624    DEFAULT_PALETTE_SIZE_8_UV_COLOR_CDF, DEFAULT_PALETTE_SIZE_8_Y_COLOR_CDF,
1625    DEFAULT_PALETTE_UV_MODE_CDF, DEFAULT_PALETTE_UV_SIZE_CDF, DEFAULT_PALETTE_Y_MODE_CDF,
1626    DEFAULT_PALETTE_Y_SIZE_CDF, DEFAULT_PARTITION_W128_CDF, DEFAULT_PARTITION_W16_CDF,
1627    DEFAULT_PARTITION_W32_CDF, DEFAULT_PARTITION_W64_CDF, DEFAULT_PARTITION_W8_CDF,
1628    DEFAULT_REF_MV_CDF, DEFAULT_SEGMENT_ID_CDF, DEFAULT_SEGMENT_ID_PREDICTED_CDF,
1629    DEFAULT_SINGLE_REF_CDF, DEFAULT_SKIP_CDF, DEFAULT_SKIP_MODE_CDF, DEFAULT_TXB_SKIP_CDF,
1630    DEFAULT_TXFM_SPLIT_CDF, DEFAULT_TX_16X16_CDF, DEFAULT_TX_32X32_CDF, DEFAULT_TX_64X64_CDF,
1631    DEFAULT_TX_8X8_CDF, DEFAULT_UNI_COMP_REF_CDF, DEFAULT_UV_MODE_CFL_ALLOWED_CDF,
1632    DEFAULT_UV_MODE_CFL_NOT_ALLOWED_CDF, DEFAULT_WEDGE_INDEX_CDF, DEFAULT_WEDGE_INTER_INTRA_CDF,
1633    DEFAULT_Y_MODE_CDF, DEFAULT_ZERO_MV_CDF, DELTA_LF_SMALL, DELTA_Q_SMALL, DIRECTIONAL_MODES,
1634    DRL_MODE_CONTEXTS, EOB_COEF_CONTEXTS, EXT_PARTITION_TYPES, FILTER_INTRA_MODE_TO_INTRA_DIR,
1635    FLIPADST_ADST, FLIPADST_DCT, FLIPADST_FLIPADST, FRAME_LF_COUNT, FWD_REFS, H_ADST, H_DCT,
1636    H_FLIPADST, IDTX, INTERINTRA_MODES, INTERP_FILTERS, INTERP_FILTER_CONTEXTS, INTERP_FILTER_NONE,
1637    INTER_TX_TYPE_SET1_SIZES, INTER_TX_TYPE_SET3_SIZES, INTRABC_DELAY_PIXELS, INTRA_FILTER_MODES,
1638    INTRA_MODES, INTRA_MODE_CONTEXT, INTRA_MODE_CONTEXTS, INTRA_TX_TYPE_SET1_SIZES,
1639    INTRA_TX_TYPE_SET2_SIZES, IS_INTER_CONTEXTS, LEVEL_CONTEXTS, MAG_REF_OFFSET_WITH_TX_CLASS,
1640    MAX_ANGLE_DELTA, MAX_TX_DEPTH, MAX_TX_DEPTH_TABLE, MAX_TX_SIZE_RECT, MAX_VARTX_DEPTH,
1641    MI_HEIGHT_LOG2, MI_SIZE, MI_SIZE_LOG2, MI_WIDTH_LOG2, MODE_TO_TXFM, MOTION_MODES, MV_CLASSES,
1642    MV_COMPS, MV_CONTEXTS, MV_INTRABC_CONTEXT, MV_JOINTS, MV_OFFSET_BITS, NEW_MV_CONTEXTS,
1643    NUM_4X4_BLOCKS_HIGH, NUM_4X4_BLOCKS_WIDE, NUM_BASE_LEVELS, PALETTE_BLOCK_SIZE_CONTEXTS,
1644    PALETTE_COLORS, PALETTE_COLOR_CONTEXT, PALETTE_COLOR_CONTEXTS, PALETTE_COLOR_HASH_MULTIPLIERS,
1645    PALETTE_MAX_COLOR_CONTEXT_HASH, PALETTE_NUM_NEIGHBORS, PALETTE_SIZES, PALETTE_UV_MODE_CONTEXTS,
1646    PALETTE_Y_MODE_CONTEXTS, PARTITION_CONTEXTS, PARTITION_HORZ, PARTITION_HORZ_4,
1647    PARTITION_HORZ_A, PARTITION_HORZ_B, PARTITION_NONE, PARTITION_SPLIT, PARTITION_SUBSIZE,
1648    PARTITION_TYPES_TOTAL, PARTITION_VERT, PARTITION_VERT_4, PARTITION_VERT_A, PARTITION_VERT_B,
1649    PLANE_TYPES, REF_CONTEXTS, REF_MV_CONTEXTS, SEGMENT_ID_CONTEXTS, SEGMENT_ID_PREDICTED_CONTEXTS,
1650    SIG_COEF_CONTEXTS, SIG_COEF_CONTEXTS_2D, SIG_COEF_CONTEXTS_EOB, SIG_REF_DIFF_OFFSET,
1651    SIG_REF_DIFF_OFFSET_NUM, SINGLE_REFS, SIZE_GROUP, SKIP_CONTEXTS, SKIP_MODE_CONTEXTS,
1652    SPLIT_TX_SIZE, TXB_SKIP_CONTEXTS, TXFM_PARTITION_CONTEXTS, TX_16X16, TX_16X32, TX_16X4,
1653    TX_16X64, TX_16X8, TX_32X16, TX_32X32, TX_32X64, TX_32X8, TX_4X16, TX_4X4, TX_4X8, TX_64X16,
1654    TX_64X32, TX_64X64, TX_8X16, TX_8X32, TX_8X4, TX_8X8, TX_CLASS_2D, TX_CLASS_HORIZ,
1655    TX_CLASS_VERT, TX_HEIGHT, TX_SET_DCTONLY, TX_SET_INTER_1, TX_SET_INTER_2, TX_SET_INTER_3,
1656    TX_SET_INTRA_1, TX_SET_INTRA_2, TX_SET_TYPES_INTER, TX_SET_TYPES_INTRA, TX_SIZES, TX_SIZES_ALL,
1657    TX_SIZE_CONTEXTS, TX_SIZE_SQR_UP, TX_TYPES, TX_TYPES_INTRA_SET1, TX_TYPES_INTRA_SET2,
1658    TX_TYPES_SET2, TX_TYPES_SET3, TX_TYPE_IN_SET_INTER, TX_TYPE_IN_SET_INTRA, TX_WIDTH,
1659    TX_WIDTH_LOG2, UNIDIR_COMP_REFS, UV_INTRA_MODES_CFL_ALLOWED, UV_INTRA_MODES_CFL_NOT_ALLOWED,
1660    V_ADST, V_DCT, V_FLIPADST, V_PRED, WEDGE_TYPES, ZERO_MV_CONTEXTS,
1661};
1662#[doc(hidden)]
1663pub use cdf::{
1664    GM_TYPE_AFFINE, GM_TYPE_IDENTITY, GM_TYPE_ROTZOOM, GM_TYPE_TRANSLATION, MAX_REF_MV_STACK_SIZE,
1665    MODE_GLOBALMV, MODE_GLOBAL_GLOBALMV, MODE_NEARESTMV, MODE_NEAREST_NEARESTMV,
1666    MODE_NEAREST_NEWMV, MODE_NEARMV, MODE_NEAR_NEARMV, MODE_NEAR_NEWMV, MODE_NEWMV,
1667    MODE_NEW_NEARESTMV, MODE_NEW_NEARMV, MODE_NEW_NEWMV, MV_BORDER, REF_CAT_LEVEL,
1668};
1669// r205: §7.9 motion-field-estimation helpers + the §7.10.2.5 /
1670// §7.10.2.6 temporal-scan grid + §3 constants.
1671#[doc(hidden)]
1672pub use cdf::{
1673    get_block_position, get_mv_projection, MotionFieldMvs, DIV_MULT, MAX_OFFSET_HEIGHT,
1674    MAX_OFFSET_WIDTH, MFMV_INVALID, MFMV_STACK_SIZE, MV_IN_USE_BITS,
1675};
1676// r178: §5.11.x `read_interpolation_filter` named ordinals + readout
1677// aggregate, plus the §5.11.28 / §5.11.29 readout aggregates exposed
1678// alongside (each `DecodedInterBlockModeInfo` field references them).
1679#[doc(hidden)]
1680pub use cdf::{
1681    CompoundTypeReadout, InterIntraReadout, InterpolationFilterReadout, BILINEAR, EIGHTTAP,
1682    EIGHTTAP_SHARP, EIGHTTAP_SMOOTH, SWITCHABLE,
1683};
1684// r179: §5.11.39 `coeffs` per-TU readout aggregate ([`cdf::CoefficientsReadout`])
1685// surfaced through [`cdf::PartitionWalker::coefficients`].
1686#[doc(hidden)]
1687pub use cdf::CoefficientsReadout;
1688// r180: §5.11.33 `compute_prediction()` per-plane dispatcher readout
1689// ([`cdf::ComputePredictionReadout`] + [`cdf::PlanePredictionTask`])
1690// surfaced through [`cdf::PartitionWalker::compute_prediction`], plus
1691// the §7.11.2.5 DC-PRED sample-generation leaf
1692// ([`cdf::predict_intra_dc_pred`]) and the §5.11.38
1693// `get_plane_residual_size` / `SUBSAMPLED_SIZE` helpers.
1694#[doc(hidden)]
1695pub use cdf::{
1696    get_plane_residual_size, predict_intra_dc_pred, ComputePredictionReadout, PlanePredictionTask,
1697    COMPUTE_PRED_MODE_INTER, SUBSAMPLED_SIZE,
1698};
1699// r186: §7.11.2.4 step-10 V_PRED + step-11 H_PRED sample-generation
1700// leaves admitted to the dispatcher alongside DC_PRED; plus the
1701// `DC_PRED` / `H_PRED` named §6.10.x intra-mode ordinals (`V_PRED`
1702// is already exported via the r180 export block above); plus the
1703// §7.11.2.1 `AboveRow[]` / `LeftCol[]` neighbour-array derivation
1704// helpers that read `CurrFrame[plane]` and feed the leaves.
1705#[doc(hidden)]
1706pub use cdf::{
1707    derive_above_row, derive_left_col, predict_intra_h_pred, predict_intra_v_pred, DC_PRED, H_PRED,
1708};
1709// r330: §7.11.4 palette prediction process — the per-transform-block
1710// sample-generation leaf that consumes the §5.11.49 `ColorMap{Y,UV}`
1711// index map (surfaced on `DecodedBlock` in r325) plus the §5.11.46
1712// `PaletteColors{Y,U,V}[ ]` table to write palette-predicted samples.
1713#[doc(hidden)]
1714pub use cdf::predict_palette;
1715// r187: §7.11.2.2 PAETH_PRED + §7.11.2.6 SMOOTH / SMOOTH_V /
1716// SMOOTH_H_PRED sample-generation leaves admitted to the dispatcher
1717// alongside {DC, V, H}_PRED — seven of thirteen intra modes now
1718// covered, leaving the six directional D-modes (D45 / D67 / D113 /
1719// D135 / D157 / D203) for the next arc. Plus the §7.11.2.1
1720// `AboveRow[-1]` / `LeftCol[-1]` corner-sample derivation
1721// ([`cdf::derive_above_left`]) that PAETH consumes, plus the named
1722// §6.10.x intra-mode ordinals (`SMOOTH_PRED` / `SMOOTH_V_PRED` /
1723// `SMOOTH_H_PRED` / `PAETH_PRED`) and the §7.11.2.6 `Sm_Weights_Tx_*`
1724// weight tables verbatim from av1-spec p.508.
1725#[doc(hidden)]
1726pub use cdf::{
1727    derive_above_left, predict_intra_paeth_pred, predict_intra_smooth_h_pred,
1728    predict_intra_smooth_pred, predict_intra_smooth_v_pred, PAETH_PRED, SMOOTH_H_PRED, SMOOTH_PRED,
1729    SMOOTH_V_PRED, SM_WEIGHTS_TX_16X16, SM_WEIGHTS_TX_32X32, SM_WEIGHTS_TX_4X4,
1730    SM_WEIGHTS_TX_64X64, SM_WEIGHTS_TX_8X8,
1731};
1732// r188: §7.11.2.4 six non-degenerate directional D-mode sample-
1733// generation leaves (`predict_intra_directional` keyed by `pAngle`;
1734// `predict_intra_d_mode` keyed by §6.10.x intra-mode ordinal) admitted
1735// to the dispatcher alongside the seven non-D modes — all 13 §6.10.x
1736// Y intra modes now covered. Plus the §7.11.2.4 `Mode_To_Angle[]` +
1737// `Dr_Intra_Derivative[ 90 ]` tables (av1-spec p.485 / p.487) and
1738// `ANGLE_STEP = 3` (av1-spec p.485). Plus the §7.11.2.{7, 9, 10, 11,
1739// 12} intra-edge helpers (`filter_corner` /
1740// `intra_edge_filter_strength_selection` /
1741// `intra_edge_upsample_selection` / `intra_edge_upsample` /
1742// `intra_edge_filter`) — the spec's pre-pass helpers, exposed as
1743// standalone functions; the dispatcher runs the no-upsample / no-
1744// filter path of step-4 (strength == 0, useUpsample == 0) so the body
1745// produces the correct shape with the lower-quality un-filtered edges.
1746// Plus the six named §6.10.x D-mode intra-mode ordinals (`D45_PRED` /
1747// `D135_PRED` / `D113_PRED` / `D157_PRED` / `D203_PRED` / `D67_PRED`).
1748#[doc(hidden)]
1749pub use cdf::{
1750    filter_corner, intra_edge_filter, intra_edge_filter_strength_selection, intra_edge_upsample,
1751    intra_edge_upsample_selection, predict_intra_d_mode, predict_intra_directional, ANGLE_STEP,
1752    D113_PRED, D135_PRED, D157_PRED, D203_PRED, D45_PRED, D67_PRED, DR_INTRA_DERIVATIVE,
1753    INTRA_EDGE_KERNEL, INTRA_EDGE_KERNELS, INTRA_EDGE_TAPS, MODE_TO_ANGLE,
1754};
1755// r181: §5.11.34 `residual()` outer-dispatch readout
1756// ([`cdf::ResidualReadout`] + [`cdf::ResidualTuTask`]) surfaced
1757// through [`cdf::PartitionWalker::residual`], plus the §5.11.37
1758// per-plane transform-size lookup [`cdf::get_tx_size`].
1759#[doc(hidden)]
1760pub use cdf::{get_tx_size, ResidualReadout, ResidualTuTask};
1761// r183: §7.12.2 dequantization-function tables + helpers + §7.12.3
1762// step-1 dequantization loop ([`cdf::dequantize_step1`]) + §5.11.47
1763// `transform_type` per-TU S() reader ([`cdf::PartitionWalker::transform_type`])
1764// — replaces the r182 placeholder identity dequant + `DCT_DCT`
1765// hard-code in the `residual()` dispatcher. The `transform_type`
1766// inversion tables `TX_TYPE_INTER_INV_SET{1,2,3}` /
1767// `TX_TYPE_INTRA_INV_SET{1,2}` are surfaced for caller use; the
1768// per-block [`cdf::ResidualContext`] aggregate bundles the
1769// `base_q_idx` / segmentation / `delta_q_*` / `using_qmatrix` state
1770// the dispatcher needs.
1771#[doc(hidden)]
1772pub use cdf::{
1773    ac_q, dc_q, dequant_denom, dequantize_step1, get_ac_quant, get_dc_quant, get_qindex,
1774    QuantizerParams, ResidualContext, TransformTypeReadout, AC_QLOOKUP, DC_QLOOKUP,
1775    TX_TYPE_INTER_INV_SET1, TX_TYPE_INTER_INV_SET2, TX_TYPE_INTER_INV_SET3, TX_TYPE_INTRA_INV_SET1,
1776    TX_TYPE_INTRA_INV_SET2,
1777};
1778// r182: §7.13 inverse transform (av1-spec p.295-307) — the
1779// `inverse_transform_2d` 2D dispatcher consumes the §7.12.3 step-1
1780// `Dequant[][]` buffer (placeholder identity-dequant of `Quant[]`
1781// in the walker today) and returns the §7.13.3 `Residual[][]`
1782// buffer the §7.12.3 step-3 frame-buffer write would consume. The
1783// 1D primitives (`inverse_dct` / `inverse_adst` / `inverse_wht4` /
1784// `inverse_identity`) and the §7.13.2.1 butterfly building blocks
1785// (`butterfly_b` / `butterfly_h` / `cos128` / `sin128` / `brev`)
1786// are exposed standalone for bit-exact testing.
1787pub use codec_config::Av1CodecConfig;
1788#[doc(hidden)]
1789pub use frame_header::{
1790    parse_frame_header, parse_frame_header_with_refs, FrameHeader, FrameSize, FrameType,
1791    InterFrameRefs, RefInfo, NUM_REF_FRAMES, PRIMARY_REF_NONE, SUPERRES_DENOM_BITS,
1792    SUPERRES_DENOM_MIN, SUPERRES_NUM,
1793};
1794#[doc(hidden)]
1795pub use obu::{parse_leb128, parse_obu, ObuDescriptor, ObuIter, ObuType};
1796#[doc(hidden)]
1797pub use sequence_header::{
1798    parse_sequence_header, ColorConfig, DecoderModelInfo, OperatingParametersInfo, OperatingPoint,
1799    SequenceHeader, TimingInfo,
1800};
1801#[doc(hidden)]
1802pub use superres::{
1803    upscale_frame, upscale_plane, upscale_sample, SuperresError, SuperresFrameContext,
1804    FILTER_BITS as SUPERRES_TAP_FILTER_BITS, SUPERRES_EXTRA_BITS, SUPERRES_FILTER_BITS,
1805    SUPERRES_FILTER_OFFSET, SUPERRES_FILTER_SHIFTS, SUPERRES_FILTER_TAPS, SUPERRES_SCALE_BITS,
1806    SUPERRES_SCALE_MASK, UPSCALE_FILTER,
1807};
1808#[doc(hidden)]
1809pub use symbol_decoder::SymbolDecoder;
1810#[doc(hidden)]
1811pub use tile_info::{
1812    parse_tile_info, TileInfo, MAX_TILE_AREA, MAX_TILE_COLS, MAX_TILE_ROWS, MAX_TILE_WIDTH,
1813};
1814#[doc(hidden)]
1815pub use transform::{
1816    brev, butterfly_b, butterfly_h, clip3, cos128, inverse_adst, inverse_adst16, inverse_adst4,
1817    inverse_adst8, inverse_adst_input_permute, inverse_adst_output_permute, inverse_dct,
1818    inverse_dct_permute, inverse_identity, inverse_identity16, inverse_identity32,
1819    inverse_identity4, inverse_identity8, inverse_transform_2d, inverse_wht4, round2, sin128,
1820    COS128_LOOKUP, SINPI_1_9, SINPI_2_9, SINPI_3_9, SINPI_4_9, TRANSFORM_ROW_SHIFT,
1821};
1822// r189: §7.11.3 Inter prediction process (av1-spec p.257-265) —
1823// translational single-reference MC kernel. Three sample-generation
1824// helpers admitted standalone alongside the §7.11.2 intra leaves:
1825// §7.11.3.2 [`inter_pred::rounding_variables`] (the
1826// `(InterRound0, InterRound1, InterPostRound)` rounding-shift
1827// derivation), §7.11.3.3 [`inter_pred::motion_vector_scaling`] (the
1828// `(startX, startY, stepX, stepY)` ref-coord derivation, 10
1829// fractional bits), and §7.11.3.4 [`inter_pred::block_inter_prediction`]
1830// (the 8-tap horizontal + vertical convolution kernel with `Clip3`
1831// boundary clamp and Round2-after-each-pass). Plus the
1832// [`inter_pred::SUBPEL_FILTERS`] table (`Subpel_Filters[6][16][8]`
1833// verbatim from av1-spec p.263-265) and the
1834// [`inter_pred::select_interp_filter_small_block`] remap (`w <= 4` /
1835// `h <= 4` → `EIGHTTAP_4TAP` / `EIGHTTAP_SMOOTH_4TAP`). The §7.11.3
1836// constants `FILTER_BITS` / `SUBPEL_BITS` / `SUBPEL_MASK` /
1837// `SCALE_SUBPEL_BITS` / `REF_SCALE_SHIFT` and the
1838// `EIGHTTAP_4TAP` / `EIGHTTAP_SMOOTH_4TAP` filter ordinals are
1839// surfaced. The §5.11.33 `compute_prediction` dispatcher now also
1840// admits the `is_inter == 1` arm — it emits one
1841// [`PlanePredictionTask`] per `(plane, i8, j8)` `8 × 8` sub-block per
1842// the §7.11.3.1 driver outer loop with `mode = COMPUTE_PRED_MODE_INTER`.
1843// As of r194 the per-task `predict_inter` body lands as
1844// [`inter_pred::predict_inter`] (single-reference translational SIMPLE
1845// arm), and r201 wires the step-14 compound arm (five
1846// `compound_type` mechanisms — `COMPOUND_AVERAGE` / `COMPOUND_DISTANCE`
1847// / `COMPOUND_WEDGE` / `COMPOUND_DIFFWTD` / `COMPOUND_INTRA` —
1848// dispatched through the new [`inter_pred::CompoundParams`] arg). r202
1849// wires the WARPED_CAUSAL motion-mode arm: the step-2/3/6/7 `useWarp`
1850// derivation now picks between LOCALWARP / GLOBAL_GLOBALMV /
1851// translational fallback per av1-spec p.257 lines 14308-14349, and the
1852// step-12 per-8×8 `block_warp` loop is driven from
1853// [`inter_pred::predict_inter`] through the new
1854// [`inter_pred::WarpDriverParams`] arg. r203 wires the OBMC arm into
1855// the same driver: the §7.11.3.9 above-row + left-column mi-grid
1856// neighbour walk + per-candidate §7.11.3.10 overlap blend run inside
1857// [`inter_pred::predict_inter`]'s post-step on `motion_mode == OBMC`
1858// against the caller-resolved [`inter_pred::ObmcParams`] context.
1859// All four motion modes (SIMPLE / WARPED_CAUSAL / OBMC + compound)
1860// are now driver-side complete.
1861#[doc(hidden)]
1862pub use cdef::{
1863    cdef_block, cdef_direction, cdef_filter_block, cdef_frame, constrain, CdefFrameContext,
1864    CDEF_DIRECTIONS, CDEF_PRI_TAPS, CDEF_SEC_TAPS, CDEF_UV_DIR, DIV_TABLE,
1865};
1866#[doc(hidden)]
1867pub use film_grain::{
1868    add_noise_synthesis, film_grain_synthesis, generate_grain, scale_lut, scaling_lookup_init,
1869    GrainArrays, RandomRegister, ScalingLut, LUMA_GRAIN_H, LUMA_GRAIN_W, MC_IDENTITY,
1870};
1871#[doc(hidden)]
1872pub use inter_pred::{
1873    block_inter_prediction, block_shape, block_warp, clip1_single_ref, compound_distance_blend,
1874    difference_weight_mask, distance_weights, get_relative_dist, intra_mode_variant_mask,
1875    mask_blend, mask_blend_interintra, master_mask_table, motion_vector_scaling, predict_inter,
1876    reconstruct_inter_block, reconstruct_inter_block_interintra, reconstruct_inter_block_obmc,
1877    reconstruct_inter_block_warp, reconstruct_inter_frame, reconstruct_inter_intra_block,
1878    reconstruct_inter_intra_from_dispatch, resolve_divisor, rounding_variables,
1879    select_interp_filter_small_block, setup_shear, warp_estimation, wedge_mask, CompoundParams,
1880    DistanceWeights, Divisor, GridObmcContext, GridWarpContext, InterIntraLeaf, InterIntraModeInfo,
1881    InterIntraWedgeModeInfo, InterModeInfo, InterModeInfoGrid, LocalWarp, MvScale, ObmcNeighbour,
1882    ObmcParams, PlaneReconContext, PlaneRefSpec, PredictInterRef, RefFrameStoreEntry, RoundingVars,
1883    ShearParams, WarpDriverParams, WarpSampleCand, COMPOUND_AVERAGE, COMPOUND_DIFFWTD,
1884    COMPOUND_DISTANCE, COMPOUND_INTRA, COMPOUND_WEDGE, DIV_LUT, DIV_LUT_BITS, DIV_LUT_NUM,
1885    DIV_LUT_PREC_BITS, EIGHTTAP_4TAP, EIGHTTAP_SMOOTH_4TAP, FILTER_BITS as INTER_FILTER_BITS,
1886    II_DC_PRED, II_H_PRED, II_SMOOTH_PRED, II_V_PRED, II_WEIGHTS_1D,
1887    LEAST_SQUARES_SAMPLES_MAX as INTER_LEAST_SQUARES_SAMPLES_MAX, LS_MV_MAX, MASK_MASTER_SIZE,
1888    MAX_FRAME_DISTANCE, MAX_SB_SIZE, QUANT_DIST_LOOKUP, QUANT_DIST_WEIGHT, REF_SCALE_SHIFT,
1889    SCALE_SUBPEL_BITS, SUBPEL_BITS, SUBPEL_FILTERS, SUBPEL_MASK, USE_WARP_GLOBAL, USE_WARP_LOCAL,
1890    WARPEDDIFF_PREC_BITS, WARPEDMODEL_NONDIAGAFFINE_CLAMP, WARPEDMODEL_TRANS_CLAMP,
1891    WARPEDPIXEL_PREC_SHIFTS, WARPED_FILTERS, WARP_PARAM_REDUCE_BITS, WARP_WARPEDMODEL_PREC_BITS,
1892    WEDGE_BITS, WEDGE_CODEBOOK, WEDGE_DIRECTIONS, WEDGE_HORIZONTAL, WEDGE_MASTER_OBLIQUE_EVEN,
1893    WEDGE_MASTER_OBLIQUE_ODD, WEDGE_MASTER_VERTICAL, WEDGE_OBLIQUE117, WEDGE_OBLIQUE153,
1894    WEDGE_OBLIQUE27, WEDGE_OBLIQUE63, WEDGE_VERTICAL,
1895};
1896#[doc(hidden)]
1897pub use loop_filter::{
1898    adaptive_filter_strength, adaptive_filter_strength_selection, filter_mask, filter_size,
1899    loop_filter_edge, loop_filter_frame, narrow_filter, sample_filtering, wide_filter,
1900    FilterMaskOutput, FilterStrength, LoopFilterFrameContext, PlaneBuffer,
1901};
1902#[doc(hidden)]
1903pub use loop_restoration::{
1904    count_units_in_frame, derive_block_geometry, get_source_sample, loop_restoration_frame,
1905    loop_restore_block, self_guided_filter, wiener_coefficients, wiener_filter,
1906    LoopRestorationFrameContext, LrBlockGeometry, FILTER_BITS as LR_FILTER_BITS,
1907    SGRPROJ_MTABLE_BITS, SGRPROJ_PARAMS_BITS, SGRPROJ_PRJ_BITS, SGRPROJ_PRJ_SUBEXP_K,
1908    SGRPROJ_RECIP_BITS, SGRPROJ_RST_BITS, SGRPROJ_SGR_BITS, SGRPROJ_XQD_MAX, SGRPROJ_XQD_MID,
1909    SGRPROJ_XQD_MIN, SGR_PARAMS, WIENER_COEFFS, WIENER_TAPS_K, WIENER_TAPS_MAX, WIENER_TAPS_MID,
1910    WIENER_TAPS_MIN,
1911};
1912#[doc(hidden)]
1913pub use uncompressed_header_tail::{
1914    parse_cdef_params, parse_delta_lf_params, parse_delta_q_params, parse_film_grain_params,
1915    parse_global_motion_params, parse_interpolation_filter, parse_loop_filter_params,
1916    parse_lr_params, parse_quantization_params, parse_segmentation_params, parse_tx_mode,
1917    prev_gm_params_default, CdefParams, DeltaLfParams, DeltaQParams, FilmGrainContext,
1918    FilmGrainParams, FrameRestorationType, GlobalMotionParams, InterpolationFilter,
1919    LoopFilterParams, LrParams, QuantizationParams, SegmentationParams, TxMode, WarpModelType,
1920    ALTREF2_FRAME, ALTREF_FRAME, BIDIR_COMP_REFERENCE, BWDREF_FRAME, CDEF_MAX_STRENGTHS,
1921    COMPOUND_REFERENCE, GM_ABS_ALPHA_BITS, GM_ABS_TRANS_BITS, GM_ABS_TRANS_ONLY_BITS,
1922    GM_ALPHA_PREC_BITS, GM_TRANS_ONLY_PREC_BITS, GM_TRANS_PREC_BITS, GOLDEN_FRAME, INTRA_FRAME,
1923    LAST2_FRAME, LAST3_FRAME, LAST_FRAME, LOOP_FILTER_MODE_DELTAS_DEFAULT,
1924    LOOP_FILTER_REF_DELTAS_DEFAULT, MAX_AR_COEFFS_UV, MAX_AR_COEFFS_Y, MAX_LOOP_FILTER,
1925    MAX_NUM_CHROMA_POINTS, MAX_NUM_Y_POINTS, MAX_SEGMENTS, REFS_PER_FRAME,
1926    RESTORATION_TILESIZE_MAX, SEGMENTATION_FEATURE_BITS, SEGMENTATION_FEATURE_MAX,
1927    SEGMENTATION_FEATURE_SIGNED, SEG_LVL_ALT_LF_U, SEG_LVL_ALT_LF_V, SEG_LVL_ALT_LF_Y_H,
1928    SEG_LVL_ALT_LF_Y_V, SEG_LVL_ALT_Q, SEG_LVL_GLOBALMV, SEG_LVL_MAX, SEG_LVL_REF_FRAME,
1929    SEG_LVL_SKIP, SINGLE_REFERENCE, TOTAL_REFS_PER_FRAME, TX_MODES, UNIDIR_COMP_REFERENCE,
1930    WARPEDMODEL_PREC_BITS,
1931};
1932
1933/// Crate-local error type.
1934///
1935/// `#[non_exhaustive]` so future variants (each new round-work commit
1936/// can grow new failure modes as the clean-room rebuild expands) are
1937/// additive — not semver-breaking — for downstream callers' `match`
1938/// arms.
1939#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1940#[non_exhaustive]
1941pub enum Error {
1942    /// A high-level API path is still a scaffold pending the
1943    /// clean-room rebuild.
1944    NotImplemented,
1945    /// The input ended in the middle of an OBU header, extension
1946    /// header, `leb128()` value, or declared payload.
1947    UnexpectedEnd,
1948    /// `obu_forbidden_bit` was set, in violation of §6.2.2.
1949    ForbiddenBitSet,
1950    /// The OBU header had `obu_has_size_field == 0`; the walker only
1951    /// accepts the §5.2 low-overhead format with explicit sizes.
1952    MissingSizeField,
1953    /// A `leb128()` value exceeded `(1 << 32) - 1`, the §4.10.5
1954    /// bitstream-conformance cap.
1955    Leb128Overflow,
1956    /// A `leb128()` encoding consumed more than 8 bytes — §4.10.5
1957    /// requires the MSB of the 8th byte to be 0.
1958    Leb128TooLong,
1959    /// An `obu_size` value did not fit in `usize` on this target.
1960    SizeOverflow,
1961    /// `seq_profile` was greater than 2 — values 3..=7 are reserved
1962    /// per §6.4.1.
1963    ReservedProfile(u8),
1964    /// `reduced_still_picture_header == 1` but `still_picture == 0`,
1965    /// in violation of the §6.4.1 conformance requirement.
1966    ReducedStillRequiresStill,
1967    /// `idLen` (= `additional_frame_id_length_minus_1 +
1968    /// `delta_frame_id_length_minus_2 + 3`) exceeded the §6.8.2
1969    /// requirement that the bit width of `display_frame_id` /
1970    /// `current_frame_id` must not exceed 16.
1971    InvalidIdLen,
1972    /// The frame-header parser hit a `temporal_point_info()` call
1973    /// site (§5.9.31) — i.e. `decoder_model_info_present_flag &&
1974    /// !equal_picture_interval`. Decoder-model frame timing isn't
1975    /// implemented yet; every fixture in this round's corpus parses
1976    /// without ever triggering this path.
1977    TemporalPointInfoUnsupported,
1978    /// r428 — an Annex B length-delimited bitstream violated the
1979    /// Annex B.2/B.3 rules: nested sizes that do not tile their
1980    /// container, an `obu_size`/`obu_length` inconsistency, or a
1981    /// temporal delimiter anywhere but the first OBU of a temporal
1982    /// unit's first frame unit.
1983    AnnexBInvalid,
1984    /// Retained for API stability. The §5.9.2 `if (!FrameIsIntra ||
1985    /// refresh_frame_flags != allFrames) { if (error_resilient_mode &&
1986    /// enable_order_hint) { ... } }` ref_order_hint walk is now parsed
1987    /// (the bits are consumed; the conformance-only `RefValid[i] = 0`
1988    /// invalidation against the session's `RefOrderHint[]` has no effect
1989    /// on the parse), so the inter-frame header path no longer returns
1990    /// this variant. It is kept to avoid a breaking enum change.
1991    RefOrderHintWalkUnsupported,
1992    /// `exit_symbol()` was invoked while `SymbolMaxBits` was strictly
1993    /// less than `-14`, violating the §8.2.4 bitstream-conformance
1994    /// requirement that `SymbolMaxBits >= -14` at exit.
1995    SymbolExitUnderflow,
1996    /// The §5.11.49 `palette_tokens` walker
1997    /// ([`crate::palette_tokens_plane`]) was called with caller-supplied
1998    /// dimensions / palette size / buffer that violate the spec's
1999    /// implicit preconditions (palette size outside `2..=PALETTE_COLORS`,
2000    /// `onscreen_{w,h}` zero or greater than `block_{w,h}`,
2001    /// `color_index_map >= palette_size`, stride below `block_width`,
2002    /// or output buffer smaller than `block_height * stride`). The
2003    /// spec gates the walker behind §5.11.49's `if (PaletteSize{Y,UV})`
2004    /// guard plus §5.11.x block-size discipline, so a conformant call
2005    /// site never produces this.
2006    InvalidPaletteWalkArgs,
2007    /// During the §5.11.49 palette diagonal walk, the §5.11.50
2008    /// `ColorContextHash` landed on an unmapped entry of
2009    /// `Palette_Color_Context[]` (the slots that hold `-1`: hashes
2010    /// `0`, `1`, `3`, `4`). The spec sweep over every realisable
2011    /// neighbour combination at every palette size shows these hashes
2012    /// are unreachable from a conformant decode state, so producing
2013    /// one is a bitstream-conformance violation (or a buffer-aliasing
2014    /// bug in the caller's `color_map`).
2015    PaletteColorContextUnmapped,
2016    /// The §5.11.4 [`crate::PartitionWalker::decode_partition`] walker
2017    /// hit an out-of-range `bSize` (>= [`crate::BLOCK_SIZES`]), an
2018    /// out-of-range `partition`, a `bsl` that did not select a
2019    /// partition CDF row (a `bsl == 0` or `bsl > 5`), or a
2020    /// [`crate::partition_subsize`] lookup that returned
2021    /// [`crate::BLOCK_INVALID`]. Each of these is a caller bug — the
2022    /// public §5.11.4 entry is gated on a valid `bSize` (the
2023    /// superblock size, in `BLOCK_8X8..=BLOCK_128X128`) and the
2024    /// recursive children are constructed from in-range
2025    /// [`crate::PARTITION_SUBSIZE`] table values, so a conformant
2026    /// driver never produces one.
2027    PartitionWalkOutOfRange,
2028    /// The §5.11.5 [`crate::PartitionWalker::decode_block_syntax`]
2029    /// walker reached the §5.11.6 `mode_info()` inter-frame arm
2030    /// (`FrameIsIntra == 0`) — §5.11.18 `inter_frame_mode_info()` is
2031    /// the next round's target and currently STUBBED. Triggered by
2032    /// calling the syntax walker with `frame_is_intra = false`. The
2033    /// keyframe / intra-only path (`frame_is_intra = true`) routes
2034    /// through the implemented intra arm and never produces this.
2035    DecodeBlockInterFrameUnsupported,
2036    /// The §5.11.5 [`crate::PartitionWalker::decode_block_syntax`]
2037    /// walker reached the §5.11.16 `read_block_tx_size()` call — the
2038    /// per-block transform-size syntax-tree read. The §5.11.15 /
2039    /// §5.11.16 / §5.11.17 transform-tree readers are the next
2040    /// round's target and currently STUBBED. The walker has completed
2041    /// the §5.11.5 prologue + §5.11.6 `mode_info()` (intra arm) +
2042    /// §5.11.49 `palette_tokens()` (no-op on the no-palette path) up
2043    /// to but not including this call.
2044    ///
2045    /// As of r167 the variant is retained for API stability but is no
2046    /// longer produced by `decode_block_syntax` (the §5.11.16 reader
2047    /// landed). It remains reachable via direct calls into the walker
2048    /// from out-of-tree consumers that pre-date r167.
2049    DecodeBlockReadBlockTxSizeUnsupported,
2050    /// The §5.11.16 [`crate::PartitionWalker::read_block_tx_size`]
2051    /// reader reached the `TX_MODE_SELECT && MiSize > BLOCK_4X4 &&
2052    /// is_inter && !skip && !Lossless` arm that loops over
2053    /// `read_var_tx_size( row, col, maxTxSz, 0 )` per
2054    /// `(txH4, txW4)` sub-rectangle. §5.11.17 `read_var_tx_size` is
2055    /// the next round's target and currently STUBBED. Unreachable
2056    /// from [`crate::PartitionWalker::decode_block_syntax`] because
2057    /// that walker short-circuits the inter arm at
2058    /// [`Self::DecodeBlockInterFrameUnsupported`] upstream; surfaces
2059    /// only when callers drive [`crate::PartitionWalker::read_block_tx_size`]
2060    /// directly with `is_inter = 1`, `skip = 0`, `lossless = false`,
2061    /// `tx_mode_select = true`.
2062    ReadVarTxSizeUnsupported,
2063    /// The §5.11.5 [`crate::PartitionWalker::decode_block_syntax`]
2064    /// walker reached the §5.11.30 / §5.11.33 `compute_prediction()`
2065    /// call — the per-block intra / inter prediction sample-
2066    /// generation pass.
2067    ///
2068    /// **r180 LIFTED**: the §5.11.33 `compute_prediction()` dispatcher
2069    /// (the per-plane `for plane = 0..1 + HasChroma * 2` block walk
2070    /// with `is_inter` / `IsInterIntra` gating and §5.11.33 task
2071    /// enumeration) now runs to completion via
2072    /// [`crate::PartitionWalker::compute_prediction`] and surfaces the
2073    /// per-plane task list through
2074    /// [`crate::ComputePredictionReadout`]. The §7.11.2.5 DC-PRED
2075    /// intra-sample-generation leaf
2076    /// ([`crate::predict_intra_dc_pred`]) also lands standalone for
2077    /// caller use against a real `CurrFrame` buffer. The walker now
2078    /// reaches [`Self::DecodeBlockResidualUnsupported`] (§5.11.34)
2079    /// after `compute_prediction()`.
2080    ///
2081    /// This variant is retained as a defensive caller-bug fallback —
2082    /// the dispatcher constructs it only when
2083    /// [`crate::PartitionWalker::compute_prediction`] reports an
2084    /// inter / inter-intra / non-DC intra mode (none reachable on the
2085    /// current intra-only walker path), at which point it surfaces
2086    /// [`Self::ComputePredictionInterUnsupported`] /
2087    /// [`Self::ComputePredictionInterIntraUnsupported`] /
2088    /// [`Self::ComputePredictionIntraModeUnsupported`] instead.
2089    DecodeBlockComputePredictionUnsupported,
2090    /// **r189 LIFTED**. The §5.11.33 dispatcher's `is_inter == 1` arm
2091    /// now emits one [`crate::PlanePredictionTask`] per `(plane, i4,
2092    /// j4)` 4x4 sub-block with `mode = [`crate::COMPUTE_PRED_MODE_INTER`]`;
2093    /// the §7.11.3.4 translational MC sample-generation leaf is the
2094    /// standalone helper [`crate::block_inter_prediction`] (with
2095    /// supporting [`crate::motion_vector_scaling`] for §7.11.3.3 and
2096    /// [`crate::rounding_variables`] for §7.11.3.2). Per r191 the
2097    /// §7.11.3.11-15 compound-mask / blend bodies landed; per r192 the
2098    /// §7.11.3.5-8 WARP MC kernel landed via [`crate::block_warp`] /
2099    /// [`crate::setup_shear`] / [`crate::resolve_divisor`] /
2100    /// [`crate::warp_estimation`]. The remaining §7.11.3.9-10 OBMC
2101    /// bodies are next-arc.
2102    ///
2103    /// This variant is retained for API stability and as a defensive
2104    /// fallback — the dispatcher no longer constructs it on the
2105    /// translational `is_inter == 1` arm (the task list grows
2106    /// instead). A future caller-side enforcement (e.g. a per-task
2107    /// "warp requested" check) may re-arm it.
2108    ComputePredictionInterUnsupported,
2109    /// **r300 LIFTED — retained for API stability, no longer surfaced
2110    /// by the dispatcher.** Formerly returned when the §5.11.33
2111    /// dispatcher visited a plane whose `IsInterIntra == 1` arm fired
2112    /// (`is_inter && RefFrame[1] == INTRA_FRAME` — the inter+intra
2113    /// blend). As of r300
2114    /// [`crate::PartitionWalker::compute_prediction`] emits, per plane,
2115    /// one intra [`crate::PlanePredictionTask`] (the §7.11.3.1
2116    /// inter-intra blend's intra half, carrying the
2117    /// `interintra_mode → mode` translation per av1-spec p.82 lines
2118    /// 5142-5145) AHEAD of the `is_inter` arm's per-4x4
2119    /// `COMPUTE_PRED_MODE_INTER` tasks — both §5.11.33 guards are
2120    /// non-exclusive and fire together on an inter-intra block. The
2121    /// §7.11.3.1 blend that consumes these tasks is driven by the
2122    /// §5.11.33 frame-walk's `reconstruct_inter_block_interintra` (r299).
2123    /// This variant is no longer constructed; it is kept so the public
2124    /// [`Error`] enum stays source-compatible.
2125    ComputePredictionInterIntraUnsupported,
2126    /// The §5.11.33 dispatcher visited an intra-mode plane whose
2127    /// `mode` (the §5.11.33 `predict_intra` `mode` argument) is not
2128    /// in the §7.11.2 set the walker currently supports. As of r187
2129    /// seven standalone leaves land:
2130    ///
2131    /// * §7.11.2.5 DC_PRED — [`crate::predict_intra_dc_pred`]
2132    /// * §7.11.2.4 step-10 V_PRED — [`crate::predict_intra_v_pred`]
2133    /// * §7.11.2.4 step-11 H_PRED — [`crate::predict_intra_h_pred`]
2134    /// * §7.11.2.6 SMOOTH_PRED — [`crate::predict_intra_smooth_pred`]
2135    /// * §7.11.2.6 SMOOTH_V_PRED — [`crate::predict_intra_smooth_v_pred`]
2136    /// * §7.11.2.6 SMOOTH_H_PRED — [`crate::predict_intra_smooth_h_pred`]
2137    /// * §7.11.2.2 PAETH_PRED — [`crate::predict_intra_paeth_pred`]
2138    ///   (consumes the corner-cell sample
2139    ///   [`crate::derive_above_left`] derives)
2140    ///
2141    /// The remaining six directional D-mode intra modes
2142    /// (D45_PRED / D135_PRED / D113_PRED / D157_PRED / D203_PRED /
2143    /// D67_PRED — ordinals `3..=8`) are next-arc targets.
2144    /// Reachable only when the caller drives the dispatcher with an
2145    /// out-of-supported-set mode; the §5.11.5 walker's current
2146    /// intra-arm path always emits `YMode == DC_PRED` (the
2147    /// `intra_frame_y_mode` reader's reachable cell), so the
2148    /// §5.11.5-driven path never fires this.
2149    ComputePredictionIntraModeUnsupported,
2150    /// The §5.11.5 [`crate::PartitionWalker::decode_block_syntax`]
2151    /// walker reached the §5.11.34 `residual()` call — the per-block
2152    /// transform-coefficient read + inverse-transform + reconstruction
2153    /// pass.
2154    ///
2155    /// As of r181 the §5.11.34 outer dispatch
2156    /// (`widthChunks` / `heightChunks` per-chunk loop +
2157    /// §5.11.36 `transform_tree` recursion + §5.11.35
2158    /// `transform_block` direct iteration) is wired into the walker
2159    /// through [`crate::PartitionWalker::residual`]; on the `skip ==
2160    /// true` arm the dispatcher completes the per-TU task enumeration
2161    /// without invoking the bitstream-reading
2162    /// [`crate::PartitionWalker::coefficients`] reader, and the walker
2163    /// advances cleanly past the §5.11.34 call site (returning the
2164    /// per-block `DecodedBlock`).
2165    ///
2166    /// This variant is retained as a defensive caller-bug fallback —
2167    /// the dispatcher constructs it only when
2168    /// [`crate::PartitionWalker::residual`] reports a configuration
2169    /// the §5.11.34 / §5.11.35 driver can't yet drive (e.g. an
2170    /// inter-luma `transform_tree` recursion on `Lossless == false`,
2171    /// or a `!skip && eob > 0` reconstruction-pass call), at which
2172    /// point it surfaces
2173    /// [`Self::ResidualReconstructUnsupported`] /
2174    /// [`Self::ResidualTransformTreeUnsupported`] /
2175    /// [`Self::ResidualCoefficientsTxSizeUnsupported`] instead.
2176    DecodeBlockResidualUnsupported,
2177    /// **Defensive fallback — no longer reached on the walker path
2178    /// as of r182.** Historically (r181) the §5.11.34
2179    /// [`crate::PartitionWalker::residual`] dispatcher surfaced this
2180    /// variant on the `!skip && eob > 0` arm when §5.11.35
2181    /// `reconstruct( plane, startX, startY, txSz )` would have run
2182    /// the §7.13 inverse transform. With r182 the §7.13 inverse
2183    /// transform is wired through [`crate::transform::inverse_transform_2d`]
2184    /// — the dispatcher now invokes it directly and stores the per-TU
2185    /// `Residual[][]` on [`crate::ResidualReadout::residuals`]. With
2186    /// r183 the §7.12.3 step-1 dequantization (`Dequant[i][j] =
2187    /// Clip3(-(1 << (7 + BitDepth)), (1 << (7 + BitDepth)) - 1,
2188    /// sign * (|Quant[pos] * q2| & 0xFFFFFF) / dqDenom)` with
2189    /// per-segment / per-plane quantizer state wires in via
2190    /// `dequantize_step1`; r204 lands the §9.5.3
2191    /// `Quantizer_Matrix[15][2][3344]` tables in [`crate::qmatrix`]
2192    /// so the `using_qmatrix && PlaneTxType < IDTX && SegQMLevel <
2193    /// 15` arm now evaluates `q2 = Round2( q * Quantizer_Matrix[
2194    /// ... ], 5 )` directly. With
2195    /// r185 the §7.12.3 step-3 frame-buffer merge
2196    /// (`CurrFrame[plane][y + yy][x + xx] = Clip1(... +
2197    /// Residual[i][j])`, including `flipLR` / `flipUD` destination
2198    /// remapping for the FLIPADST family) is applied directly
2199    /// against the walker's per-plane `CurrFrame` buffer
2200    /// (accessible via
2201    /// [`crate::PartitionWalker::curr_frame`] /
2202    /// [`crate::PartitionWalker::curr_frame_dims`]) — the dispatcher
2203    /// returns `Ok(())` with the buffer mutated in-place.
2204    ///
2205    /// Retained as a typed sentinel for callers that wire custom
2206    /// reconstruct paths through the public API and want a known
2207    /// error ordinal for "post-§7.13 caller refused to merge".
2208    ResidualReconstructUnsupported,
2209    /// The §5.11.34 [`crate::PartitionWalker::residual`] dispatcher
2210    /// reached the inter-luma
2211    /// `transform_tree(baseX, baseY, num4x4W*4, num4x4H*4)` recursion
2212    /// (the §5.11.34 `is_inter && !Lossless && !plane` arm), and the
2213    /// §5.11.36 recursion expects the §5.11.17 `read_var_tx_size`-
2214    /// stamped `InterTxSizes[ row ][ col ]` grid to drive the per-leaf
2215    /// `find_tx_size( w, h )` resolution.
2216    ///
2217    /// The §5.11.36 recursion itself runs to completion on the
2218    /// dispatcher; this variant fires only when the in-grid
2219    /// `InterTxSizes[ row ][ col ]` carries a `TX_*` ordinal whose
2220    /// `(Tx_Width, Tx_Height)` doesn't match a `(w, h)` pair the
2221    /// recursion's `find_tx_size` lookup can resolve to an in-range
2222    /// `TX_SIZES_ALL` ordinal — an out-of-spec InterTxSizes grid
2223    /// state. Unreachable on the §5.11.16 / §5.11.17 walker-driven
2224    /// `InterTxSizes` writes; reserved for direct callers of
2225    /// [`crate::PartitionWalker::residual`] that pre-populate the
2226    /// grid out-of-band.
2227    ResidualTransformTreeUnsupported,
2228    /// The §5.11.34 [`crate::PartitionWalker::residual`] dispatcher
2229    /// derived a per-leaf `txSz` (`get_tx_size( plane, TxSize )` for
2230    /// chroma, `find_tx_size( w, h )` for inter-luma transform_tree
2231    /// leaves, or `TxSize` directly for non-inter luma) that the
2232    /// §5.11.39 [`crate::PartitionWalker::coefficients`] reader
2233    /// declines (out-of-range `txSz`).
2234    ///
2235    /// Reachable only when the caller routes a non-conformant
2236    /// `tx_size` through `decode_block_syntax` — the §5.11.16 /
2237    /// §5.11.37 walker derivations all yield in-range ordinals.
2238    ResidualCoefficientsTxSizeUnsupported,
2239    /// The §5.11.18 [`crate::PartitionWalker::decode_inter_frame_mode_info`]
2240    /// walker reached the §5.11.22 `intra_block_mode_info()` call — the
2241    /// per-block intra-mode-info composite (`y_mode` / `intra_angle_info_y`
2242    /// / `uv_mode` / `read_cfl_alphas` / `intra_angle_info_uv` /
2243    /// `palette_mode_info` / `filter_intra_mode_info`). The composite is
2244    /// reachable from the §5.11.18 `else` arm of `if ( is_inter )`. The
2245    /// §5.11.22 reader itself landed in r169 as
2246    /// [`crate::PartitionWalker::decode_intra_block_mode_info`]; that
2247    /// method takes the additional sequence-header arguments
2248    /// (`has_chroma`, `allow_screen_content_tools`,
2249    /// `enable_filter_intra`, `subsampling_x`, `subsampling_y`,
2250    /// `above_palette_y`, `left_palette_y`) the §5.11.18 dispatcher
2251    /// doesn't yet thread through. The dispatcher therefore still
2252    /// short-circuits with this error; direct callers can now invoke
2253    /// the §5.11.22 reader with the missing arguments. The wiring of
2254    /// `decode_intra_block_mode_info` into the §5.11.18 dispatcher
2255    /// lands once those scalars are added to the dispatcher's
2256    /// signature.
2257    IntraBlockModeInfoUnsupported,
2258    /// The §5.11.18 [`crate::PartitionWalker::decode_inter_frame_mode_info`]
2259    /// walker reached the §5.11.23 `inter_block_mode_info()` call. As
2260    /// of r170 the dispatcher routes into the
2261    /// [`crate::PartitionWalker::decode_inter_block_mode_info`] reader
2262    /// directly; the §5.11.23 prologue (`PaletteSizeY = 0`,
2263    /// `PaletteSizeUV = 0`, §5.11.25 `read_ref_frames()`, `RefFrame[0..2]`
2264    /// assignment, `isCompound` derivation, `RefFrames[][][..]` grid
2265    /// stamp) is now implemented, and the post-prologue gap surfaces as
2266    /// [`Self::FindMvStackUnsupported`] (the §7.10.2 entry).
2267    /// This variant is retained only as a defensive caller-bug fallback
2268    /// (e.g. an out-of-range `mi_row` / `mi_col` reaching the inter arm
2269    /// before the prologue's bounds check). The §5.11.18 dispatcher no
2270    /// longer fires it on the conformant path.
2271    InterBlockModeInfoUnsupported,
2272    /// Historical stub for the §5.11.22 palette-entries gap that
2273    /// landed in r169 and was lifted in r171 with the §5.11.46
2274    /// `palette_colors_{y,u,v}[]` reader. The §5.11.46 reader — the
2275    /// `L(BitDepth)` / `L(2)` / `L(paletteBits)` cache-coded indices
2276    /// plus literal plus delta loop, merged with the §5.11.49
2277    /// `get_palette_cache(plane)` two-pointer neighbour merge — is now
2278    /// inlined into [`crate::PartitionWalker::decode_intra_block_mode_info`],
2279    /// which threads `bit_depth: u8` and stamps decoded palette state
2280    /// into the walker's `PaletteSizes[]` / `PaletteColors[]` grids.
2281    /// This variant is retained only as a defensive fallback (it is
2282    /// not constructed on the conformant path).
2283    PaletteEntriesUnsupported,
2284    /// The §5.11.23 [`crate::PartitionWalker::decode_inter_block_mode_info`]
2285    /// reader completed the §5.11.25 `read_ref_frames()` syntax tree
2286    /// (single / compound / uni-comp / bi-dir reference selection) plus
2287    /// the §5.11.23 prologue (`PaletteSizeY = 0`, `PaletteSizeUV = 0`,
2288    /// `RefFrame[0..2]` assignment, `isCompound = RefFrame[1] >
2289    /// INTRA_FRAME` derivation, walker `RefFrames[][][..]` stamp) and
2290    /// then reached the §7.10.2 `find_mv_stack(isCompound)` call.
2291    ///
2292    /// The §7.10 motion-vector-stack derivation (scan-row, scan-col,
2293    /// temporal-scan, sorting, extra-search, context-and-clamping)
2294    /// and every §5.11.23 reader that depends on its outputs
2295    /// (`compound_mode`, `new_mv`, `zero_mv`, `ref_mv`, `drl_mode`,
2296    /// `assign_mv`, `read_motion_mode`, `read_interintra_mode`,
2297    /// `read_compound_type`, `read_interpolation_filter`) are
2298    /// subsequent-arc targets. This stub fires after the §5.11.25
2299    /// `read_ref_frames` reader commits to the §8.3 adaptation state
2300    /// and stamps `RefFrames[][][..]`.
2301    ///
2302    /// As of r172 the §7.10 spatial-only path lands and is reachable
2303    /// via [`crate::PartitionWalker::find_mv_stack`]. As of r173
2304    /// `decode_inter_block_mode_info` wires `find_mv_stack` into the
2305    /// dispatcher directly and runs the post-`find_mv_stack`
2306    /// `compound_mode` / `new_mv` / `zero_mv` / `ref_mv` / `drl_mode`
2307    /// cascade. As of r174 the §5.11.31 `assign_mv` body is also
2308    /// wired; the §5.11.23 reader now short-circuits at
2309    /// [`Self::MotionModeUnsupported`] (§5.11.27 `read_motion_mode` is
2310    /// the next-arc target).
2311    ///
2312    /// This variant is retained as a defensive caller-bug fallback —
2313    /// the §5.11.18 dispatcher no longer constructs it on the
2314    /// conformant path. As of r205 the §7.10.2.5 temporal-scan +
2315    /// §7.10.2.6 temporal-sample sub-processes are wired in alongside
2316    /// the §7.10.2.1-4 spatial scans, so `use_ref_frame_mvs == true`
2317    /// also runs to completion as long as the caller supplies a
2318    /// `MotionFieldMvs` grid.
2319    FindMvStackUnsupported,
2320    /// The §5.11.23 [`crate::PartitionWalker::decode_inter_block_mode_info`]
2321    /// reader completed the §7.10.2 `find_mv_stack` call, the §5.11.23
2322    /// YMode dispatch (skip_mode / SEG_LVL_SKIP|GLOBALMV / isCompound /
2323    /// single-pred), and the per-mode RefMvIdx + drl_mode loops, then
2324    /// reached **§5.11.31 `assign_mv( isCompound )`** (av1-spec p.78).
2325    ///
2326    /// **r174 LIFTED**: the §5.11.31 / §5.11.32 `read_mv` /
2327    /// `read_mv_component` cascade is wired in, and the live gap moves
2328    /// one step down to [`Self::MotionModeUnsupported`]
2329    /// (§5.11.27 `read_motion_mode`). This variant is retained as a
2330    /// defensive caller-bug fallback — the [`crate::PartitionWalker`]
2331    /// internal `assign_mv` only surfaces this if the §5.11.7 intra-bc
2332    /// arm is reached through the inter dispatcher (not currently
2333    /// possible — that arm goes through its own caller).
2334    AssignMvUnsupported,
2335    /// **r175 LIFTED**: the §5.11.27 `read_motion_mode( isCompound )`
2336    /// body now runs to completion (with §7.10.3
2337    /// `has_overlappable_candidates` and §7.10.4 `find_warp_samples`
2338    /// helpers in place), and the §5.11.23 dispatcher surfaces the
2339    /// decoded `motion_mode` ordinal through
2340    /// [`crate::DecodedInterBlockModeInfo::motion_mode`] (with the
2341    /// §7.10.4 `NumSamples` snapshot on `num_warp_samples`). This
2342    /// variant is retained as a defensive caller-bug fallback — the
2343    /// §5.11.23 dispatcher no longer constructs it on the conformant
2344    /// path.
2345    ///
2346    /// Post-r176 the §5.11.28 `read_interintra_mode` body is also
2347    /// wired into the dispatcher (with the inner-arm
2348    /// `RefFrame[1] = INTRA_FRAME` grid-stamp override). Post-r177 the
2349    /// §5.11.29 `read_compound_type` body lands (gating on
2350    /// `enable_masked_compound` / `enable_jnt_comp`, the §3
2351    /// `Wedge_Bits[ MiSize ]` table, and the §8.3.2
2352    /// `comp_group_idx` / `compound_idx` ctx walks plus the
2353    /// `compound_type` S() / `wedge_index` S() / `wedge_sign` L(1) /
2354    /// `mask_type` L(1) sub-branches). Post-r178 the §5.11.x
2355    /// `read_interpolation_filter` body lands (gating on
2356    /// `interpolation_filter == SWITCHABLE`, the `needs_interp_filter(
2357    /// )` predicate, and the §8.3.2 `interp_filter` ctx walk plus per-
2358    /// dir `interp_filter` S() against `TileInterpFilterCdf[ ctx ]`)
2359    /// — completing the §5.11.23 inter cascade. The §5.11.18
2360    /// dispatcher's `Ok(_)` arm continues to surface
2361    /// [`Self::InterBlockModeInfoUnsupported`] pending the next-arc
2362    /// §5.11.34 `residual()` lift and a follow-on refactor that lifts
2363    /// the [`cdf::DecodedInterBlockModeInfo`] aggregate into the
2364    /// [`cdf::DecodedInterFrameModeInfo`] return path.
2365    MotionModeUnsupported,
2366    /// The arithmetic-coder state violated one of the §8.2.6 post-
2367    /// renormalization invariants:
2368    ///
2369    /// 1. `32768 ≤ SymbolRange ≤ 65535` — the §8.2.6 ordered steps 1
2370    ///    and 2 (`bits = 15 − FloorLog2(SymbolRange)`, then
2371    ///    `SymbolRange = SymbolRange << bits`) restore the range to
2372    ///    the top half of the 16-bit window after every symbol
2373    ///    decode / encode.
2374    /// 2. `SymbolValue < SymbolRange` — the §8.2.6 symbol-search loop
2375    ///    terminates exactly when `SymbolValue >= cur` lands the
2376    ///    accumulator inside the current symbol's sub-interval, and
2377    ///    the post-decode rewrite `SymbolValue -= cur` /
2378    ///    `SymbolRange = prev − cur` plus the renormalization shift
2379    ///    preserve this ordering.
2380    ///
2381    /// Surfacing this as an [`Error`] (rather than panicking on a
2382    /// `debug_assert!`) lets bitstream-conformance failures be
2383    /// reported through the normal error path. The two invariants are
2384    /// documented in §8.2.6 of the AV1 Bitstream & Decoding Process
2385    /// Specification and re-stated as cross-implementation oracles
2386    /// in `docs/video/av1/fixtures/issue_796/msac-trace.md` — the
2387    /// "Invariants observed across all 256 rows" section.
2388    SymbolStateInvariantBroken,
2389    /// The §5.11.39 lines 84-93 golomb chain (`golomb_length_bit` /
2390    /// `golomb_data_bit`) produced a `length` beyond 30 bits.
2391    ///
2392    /// A conformant stream's coefficient magnitudes are bounded far
2393    /// below `1 << 30` (§7.12.2 clamps every dequantized value into
2394    /// the signed pixel-domain range), so `length > 30` can only
2395    /// arise from a corrupt / adversarial stream — typically one
2396    /// whose payload ends mid-chain, leaving the §8.2.2 arithmetic
2397    /// decoder reading the infinite zero-bit tail. Without this cap
2398    /// the `do { length++ } while ( !golomb_length_bit )` loop of
2399    /// §5.11.39 never terminates.
2400    GolombLengthOverflow,
2401    /// A §5.9.30 `film_grain_params()` point count exceeded its
2402    /// bitstream-conformance bound (`num_y_points <= 14`,
2403    /// `num_cb_points <= 10`, `num_cr_points <= 10`). The `f(4)`
2404    /// literals can code 15 on a corrupt / adversarial stream, which
2405    /// would index past the fixed-size point arrays.
2406    FilmGrainPointCountOverflow,
2407    /// A §5.11.9 `read_segment_id()` `S()` read produced a raw
2408    /// `segment_id` symbol greater than `LastActiveSegId`, violating
2409    /// the §6.10.8 bitstream-conformance requirement that the
2410    /// postprocessed segment id (the `neg_deinterleave` return) lie
2411    /// in `0..=LastActiveSegId`. The two are equivalent:
2412    /// `neg_deinterleave( diff, pred, max )` is a bijection on
2413    /// `0..max` for any fixed `pred < max` (with
2414    /// `max = LastActiveSegId + 1`), so the postprocessed value is
2415    /// in range exactly when the raw symbol is. The §8.2.6 `S()`
2416    /// read runs against the full 8-symbol `Default_Segment_Id_Cdf`
2417    /// regardless of the frame's `LastActiveSegId`, so a corrupt /
2418    /// adversarial stream can code an out-of-range symbol whenever
2419    /// `LastActiveSegId < 7`; without this reject the
2420    /// `neg_deinterleave` `ref >= max - 1` arm would compute
2421    /// `max - diff - 1` outside its `diff < max` domain.
2422    SegmentIdOutOfRange,
2423    /// r430 — the operating point selected by external means (the
2424    /// §6.7.5 `choose_operating_point()` "explicitly signaled"
2425    /// note) does not exist in the sequence header's operating-point
2426    /// list: the index exceeds `operating_points_cnt_minus_1`. Per
2427    /// §6.7.5 a decoder must either return a value in
2428    /// `0..=operating_points_cnt_minus_1` from
2429    /// `choose_operating_point()` or abandon the decoding process —
2430    /// this is the abandon arm for an out-of-range external request.
2431    OperatingPointOutOfRange,
2432    /// r430 — a §5.12 tile-list OBU or its §7.3 large-scale-tile
2433    /// decode inputs violate the spec's conformance envelope: a
2434    /// malformed / oversized tile list (`tile_count_minus_1 > 511`,
2435    /// `anchor_frame_idx > 127`, truncated or over-long entry bytes,
2436    /// more entries than output tiles), an `anchor_tile_row` /
2437    /// `anchor_tile_col` outside the frame's tile grid, an anchor
2438    /// index beyond the supplied `AnchorFrames` array, an anchor
2439    /// whose dimensions differ from the camera frame header's, or a
2440    /// sequence / frame header outside the §7.3 bitstream-conformance
2441    /// constraint list (superres / order hints / CDEF / restoration /
2442    /// film grain enabled, non-INTER frame type, adaptive CDFs,
2443    /// non-superblock-high tiles, non-uniform tile widths, …). Also
2444    /// covers a camera frame header naming a primary reference — the
2445    /// §7.3 input contract supplies anchor PIXELS only, so a header
2446    /// that needs a reference's saved CDF state is undecodable from
2447    /// these inputs.
2448    TileListInvalid,
2449    /// r433 — a frame's tile-group OBU sequence violates the §5.11.1
2450    /// / §6.8.1 / §6.10.1 conformance rules: a tile group arriving
2451    /// with no §5.9.1 frame header pending (`SeenFrameHeader == 0`),
2452    /// a `tg_start` that does not equal the running `TileNum` (tile
2453    /// groups must cover the frame's tiles contiguously, in order), a
2454    /// frame whose tile groups do not complete inside its §7.5
2455    /// temporal unit, an `OBU_FRAME_HEADER` arriving mid-frame
2456    /// (`SeenFrameHeader == 1` — later copies must use
2457    /// `OBU_REDUNDANT_FRAME_HEADER`), an
2458    /// `OBU_REDUNDANT_FRAME_HEADER` whose §6.8.1 `frame_header_copy`
2459    /// bytes differ from the original (or with no frame in
2460    /// progress), or an `OBU_FRAME` whose embedded tile group does
2461    /// not cover the whole frame with
2462    /// `tile_start_and_end_present_flag == 0` (§6.10.1).
2463    TileGroupInvalid,
2464    /// r452 — a frame header declares a picture whose
2465    /// `UpscaledWidth * FrameHeight` exceeds the decoder's picture-size
2466    /// ceiling ([`decoder::MAX_PICTURE_SIZE`] by default, or the value
2467    /// set through [`decoder::SpecDecodeSession::set_max_picture_size`]).
2468    /// Annex A's "maximum parameters" note (level 31) leaves the
2469    /// bound to the decoder maker: "a decoder would typically decode
2470    /// pictures up to a certain maximum uncompressed picture size ...
2471    /// and not decode anything bigger than that". The check runs
2472    /// before any frame-sized buffer is reserved, so a hostile header
2473    /// cannot commit gigabytes of `MiRows * MiCols` / plane storage
2474    /// off a few dozen bytes of input.
2475    PictureSizeExceedsLimit,
2476}
2477
2478impl core::fmt::Display for Error {
2479    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2480        match self {
2481            Self::NotImplemented => write!(
2482                f,
2483                "oxideav-av1: orphan-rebuild scaffold — no decoder/encoder wired up"
2484            ),
2485            Self::UnexpectedEnd => write!(f, "oxideav-av1: unexpected end of OBU bytestream"),
2486            Self::ForbiddenBitSet => {
2487                write!(f, "oxideav-av1: obu_forbidden_bit was set (§6.2.2)")
2488            }
2489            Self::MissingSizeField => write!(
2490                f,
2491                "oxideav-av1: obu_has_size_field == 0; only the §5.2 low-overhead format is supported"
2492            ),
2493            Self::Leb128Overflow => {
2494                write!(f, "oxideav-av1: leb128 value exceeded the §4.10.5 cap")
2495            }
2496            Self::Leb128TooLong => write!(
2497                f,
2498                "oxideav-av1: leb128 encoding used more than 8 bytes (§4.10.5)"
2499            ),
2500            Self::SizeOverflow => {
2501                write!(f, "oxideav-av1: obu_size did not fit in usize on this target")
2502            }
2503            Self::ReservedProfile(p) => write!(
2504                f,
2505                "oxideav-av1: seq_profile {p} is reserved (only 0..=2 are conformant, §6.4.1)"
2506            ),
2507            Self::ReducedStillRequiresStill => write!(
2508                f,
2509                "oxideav-av1: reduced_still_picture_header == 1 requires still_picture == 1 (§6.4.1)"
2510            ),
2511            Self::InvalidIdLen => write!(
2512                f,
2513                "oxideav-av1: idLen (delta_frame_id_length_minus_2 + additional_frame_id_length_minus_1 + 3) exceeded 16 (§6.8.2)"
2514            ),
2515            Self::AnnexBInvalid => write!(
2516                f,
2517                "oxideav-av1: invalid Annex B length-delimited framing (Annex B.2/B.3)"
2518            ),
2519            Self::TemporalPointInfoUnsupported => write!(
2520                f,
2521                "oxideav-av1: temporal_point_info() / decoder-model framing not implemented yet (§5.9.31)"
2522            ),
2523            Self::RefOrderHintWalkUnsupported => write!(
2524                f,
2525                "oxideav-av1: ref_order_hint walk in §5.9.2 needs RefOrderHint[] state (not yet tracked)"
2526            ),
2527            Self::SymbolExitUnderflow => write!(
2528                f,
2529                "oxideav-av1: exit_symbol() with SymbolMaxBits < -14 (§8.2.4 conformance)"
2530            ),
2531            Self::InvalidPaletteWalkArgs => write!(
2532                f,
2533                "oxideav-av1: §5.11.49 palette_tokens_plane caller-side preconditions violated"
2534            ),
2535            Self::PaletteColorContextUnmapped => write!(
2536                f,
2537                "oxideav-av1: §5.11.49 palette ColorContextHash maps to an unreachable -1 slot of Palette_Color_Context[]"
2538            ),
2539            Self::PartitionWalkOutOfRange => write!(
2540                f,
2541                "oxideav-av1: §5.11.4 decode_partition walker hit an out-of-range bSize / partition / bsl / Partition_Subsize lookup"
2542            ),
2543            Self::DecodeBlockInterFrameUnsupported => write!(
2544                f,
2545                "oxideav-av1: §5.11.5 decode_block reached §5.11.6 mode_info inter-frame arm — §5.11.18 inter_frame_mode_info() pending next round"
2546            ),
2547            Self::DecodeBlockReadBlockTxSizeUnsupported => write!(
2548                f,
2549                "oxideav-av1: §5.11.5 decode_block reached §5.11.16 read_block_tx_size() — retained for API stability post-r167"
2550            ),
2551            Self::ReadVarTxSizeUnsupported => write!(
2552                f,
2553                "oxideav-av1: §5.11.16 read_block_tx_size reached §5.11.17 read_var_tx_size() — variable transform-tree recursion pending next round"
2554            ),
2555            Self::DecodeBlockComputePredictionUnsupported => write!(
2556                f,
2557                "oxideav-av1: §5.11.5 decode_block reached §5.11.30 compute_prediction() — defensive fallback retained post-r180 (the §5.11.33 dispatcher is now wired into the walker; see ComputePredictionIntraModeUnsupported / ComputePredictionInterUnsupported / ComputePredictionInterIntraUnsupported for the live gaps)"
2558            ),
2559            Self::ComputePredictionInterUnsupported => write!(
2560                f,
2561                "oxideav-av1: §5.11.33 compute_prediction reached §7.11.3 predict_inter — defensive fallback retained post-r192 (§7.11.3.4 translational MC kernel via inter_pred::block_inter_prediction; §7.11.3.11-15 compound bodies (wedge / diffwtd / intra / mask_blend / distance) per r191; §7.11.3.5-8 WARP MC via block_warp / setup_shear / resolve_divisor / warp_estimation per r192; §7.11.3.9-10 OBMC still pending next-arc, plus the predict_inter driver wiring)"
2562            ),
2563            Self::ComputePredictionInterIntraUnsupported => write!(
2564                f,
2565                "oxideav-av1: §5.11.33 compute_prediction IsInterIntra arm — LIFTED r300 (dispatcher now emits the intra-half + inter tasks); variant retained for API stability, no longer constructed"
2566            ),
2567            Self::ComputePredictionIntraModeUnsupported => write!(
2568                f,
2569                "oxideav-av1: §5.11.33 compute_prediction visited an intra mode outside the supported {{DC_PRED, V_PRED, H_PRED, SMOOTH_PRED, SMOOTH_V_PRED, SMOOTH_H_PRED, PAETH_PRED}} set — §7.11.2.4 directional D-modes (D45 / D67 / D113 / D135 / D157 / D203) pending next-arc"
2570            ),
2571            Self::DecodeBlockResidualUnsupported => write!(
2572                f,
2573                "oxideav-av1: §5.11.5 decode_block reached §5.11.34 residual() — defensive fallback retained post-r181 (the §5.11.34 outer dispatch + §5.11.36 transform_tree recursion + per-TU §5.11.39 coefficients() wiring is now landed; see ResidualReconstructUnsupported / ResidualTransformTreeUnsupported / ResidualCoefficientsTxSizeUnsupported for the live gaps)"
2574            ),
2575            Self::ResidualReconstructUnsupported => write!(
2576                f,
2577                "oxideav-av1: §5.11.34 residual() reached §5.11.35 reconstruct() — defensive fallback retained post-r182 (the §7.13 inverse transform is now wired through crate::transform::inverse_transform_2d; the §7.12.3 step-1 quantization-matrix derivation and step-3 frame-buffer merge remain split-off but neither raises this variant on the walker path)"
2578            ),
2579            Self::ResidualTransformTreeUnsupported => write!(
2580                f,
2581                "oxideav-av1: §5.11.34 residual() reached §5.11.36 transform_tree() with an out-of-spec InterTxSizes[r][c] grid state — find_tx_size(w, h) lookup failed"
2582            ),
2583            Self::ResidualCoefficientsTxSizeUnsupported => write!(
2584                f,
2585                "oxideav-av1: §5.11.34 residual() derived a per-leaf txSz the §5.11.39 coefficients() reader declined — caller-bug guard"
2586            ),
2587            Self::IntraBlockModeInfoUnsupported => write!(
2588                f,
2589                "oxideav-av1: §5.11.18 inter_frame_mode_info reached §5.11.22 intra_block_mode_info() — per-block intra angle / UV mode reads pending next round"
2590            ),
2591            Self::InterBlockModeInfoUnsupported => write!(
2592                f,
2593                "oxideav-av1: §5.11.18 inter_frame_mode_info reached §5.11.23 inter_block_mode_info() — defensive fallback retained post-r170 (see FindMvStackUnsupported for the live gap)"
2594            ),
2595            Self::PaletteEntriesUnsupported => write!(
2596                f,
2597                "oxideav-av1: §5.11.46 palette-entries reader — historical stub retained post-r171 (the entries reader is now inlined into decode_intra_block_mode_info; this variant is a defensive fallback only)"
2598            ),
2599            Self::FindMvStackUnsupported => write!(
2600                f,
2601                "oxideav-av1: §5.11.23 inter_block_mode_info reached §7.10.2 find_mv_stack — defensive fallback retained post-r173 (the find_mv_stack call is now wired into the dispatcher; see AssignMvUnsupported for the live gap)"
2602            ),
2603            Self::AssignMvUnsupported => write!(
2604                f,
2605                "oxideav-av1: §5.11.31 assign_mv — defensive fallback retained post-r174 (the §5.11.31 / §5.11.32 read_mv / read_mv_component cascade is now wired into the dispatcher; the live gap moved past §5.11.27 read_motion_mode in r175 to the post-`read_motion_mode` cascade, surfaced via the §5.11.18 dispatcher's Ok-arm InterBlockModeInfoUnsupported)"
2606            ),
2607            Self::MotionModeUnsupported => write!(
2608                f,
2609                "oxideav-av1: §5.11.27 read_motion_mode — defensive fallback retained post-r175 (the §5.11.27 reader is now wired into the dispatcher with §7.10.3 has_overlappable_candidates + §7.10.4 find_warp_samples; post-r176 the §5.11.28 read_interintra_mode, post-r177 the §5.11.29 read_compound_type, and post-r178 the §5.11.x read_interpolation_filter readers are also wired — completing the §5.11.23 inter cascade; the §5.11.18 dispatcher's Ok-arm continues to surface InterBlockModeInfoUnsupported pending the §5.11.34 residual lift)"
2610            ),
2611            Self::SymbolStateInvariantBroken => write!(
2612                f,
2613                "oxideav-av1: §8.2.6 post-renorm invariant broken (SymbolRange not in [32768, 65535], or SymbolValue >= SymbolRange)"
2614            ),
2615            Self::GolombLengthOverflow => write!(
2616                f,
2617                "oxideav-av1: §5.11.39 golomb_length_bit chain exceeded 30 bits — corrupt or truncated coefficient data"
2618            ),
2619            Self::FilmGrainPointCountOverflow => write!(
2620                f,
2621                "oxideav-av1: §5.9.30 film-grain point count exceeds its conformance bound (num_y_points <= 14, num_cb/cr_points <= 10)"
2622            ),
2623            Self::SegmentIdOutOfRange => write!(
2624                f,
2625                "oxideav-av1: §5.11.9 segment_id symbol exceeds LastActiveSegId — §6.10.8 conformance violation (corrupt or adversarial stream)"
2626            ),
2627            Self::OperatingPointOutOfRange => write!(
2628                f,
2629                "oxideav-av1: requested operating point exceeds operating_points_cnt_minus_1 (§6.7.5 choose_operating_point abandon arm)"
2630            ),
2631            Self::TileListInvalid => write!(
2632                f,
2633                "oxideav-av1: tile-list OBU / large-scale-tile inputs violate the §5.12/§6.11/§7.3 conformance envelope"
2634            ),
2635            Self::TileGroupInvalid => write!(
2636                f,
2637                "oxideav-av1: tile-group OBU sequence violates the §5.11.1/§6.8.1/§6.10.1 conformance rules (ordering, coverage, or frame-header copy discipline)"
2638            ),
2639            Self::PictureSizeExceedsLimit => write!(
2640                f,
2641                "oxideav-av1: UpscaledWidth * FrameHeight exceeds the decoder's picture-size ceiling (Annex A level-31 note; see decoder::MAX_PICTURE_SIZE)"
2642            ),
2643        }
2644    }
2645}
2646
2647impl std::error::Error for Error {}
2648
2649/// Decode an AV1 IVF v0 buffer into a vector of decoded [`decoder::Frame`]s.
2650///
2651/// Every stream rides the **spec-faithful frame driver**
2652/// ([`decoder::decode_av1_spec`], the conformance-corpus-validated
2653/// decoder): the full intra feature surface (lossy quant at every
2654/// coded TX size, lossless, palette, CfL, filter-intra, directional
2655/// prediction with edge filter/upsample, intra block copy), inter
2656/// GOPs (single and compound references, warped motion, OBMC,
2657/// jnt-comp, skip mode, segmentation, scaled references, global
2658/// motion, temporal MV projection, `show_existing_frame` incl. the
2659/// §7.21 KEY reload), 4:2:0 / 4:2:2 / 4:4:4 / monochrome layouts,
2660/// 8/10/12-bit output, multi-tile and 128×128-superblock frames,
2661/// delta-q, quantizer matrices, and the whole §7.4 post chain
2662/// (deblock, CDEF, superres, loop restoration, film grain). Each
2663/// SHOWN frame surfaces as [`decoder::Frame::Spec`] carrying a
2664/// [`decoder::SpecFrame`] (cropped extents, per-plane dims, 10/12-bit
2665/// as little-endian 2-byte samples).
2666///
2667/// The historical encoder-mirror acceptance arm (which claimed the
2668/// NON-conformant streams of this crate's retired early intra
2669/// encoders, pre-r409) was removed in r428 together with the mirror
2670/// emit arms — see [`decoder`] for the retirement contract.
2671///
2672/// Rejected streams surface the spec driver's typed [`Error`].
2673pub fn decode_av1(bytes: &[u8]) -> Result<Vec<decoder::Frame>, Error> {
2674    decoder::decode_av1(bytes)
2675}
2676
2677/// r430 — [`decode_av1`] at an externally selected operating point
2678/// (§6.7.5 `choose_operating_point()`): with a non-zero
2679/// `OperatingPointIdc` the §5.3.1 `drop_obu()` rule skips every OBU
2680/// carrying an extension header outside the point's temporal/spatial
2681/// layer set, so a temporally scalable stream decodes to exactly the
2682/// shown frames of the surviving layers. See
2683/// [`decoder::decode_av1_at_operating_point`].
2684pub fn decode_av1_at_operating_point(
2685    bytes: &[u8],
2686    operating_point: u8,
2687) -> Result<Vec<decoder::Frame>, Error> {
2688    decoder::decode_av1_at_operating_point(bytes, operating_point)
2689}
2690
2691/// Encode planar 4:2:0 8-bit YUV pixels into an intra-only AV1
2692/// elementary stream (IVF v0 container).
2693///
2694/// Round 409 graduates the **conformance-grade KEY-frame encoder**
2695/// ([`crate::encoder::encode_key_frame_yuv420`]) into the public
2696/// entry point: the produced stream carries real §5.11 keyframe
2697/// syntax and decodes byte-identically in this crate's spec-faithful
2698/// driver AND in independent AV1 decoders (validated as black-box
2699/// binaries). The byte input is interpreted as three contiguous
2700/// planes in `Y || U || V` order:
2701///
2702/// * `pixels[0 .. width * height]` — Y (luma) plane, row-major.
2703/// * `pixels[width * height .. width * height + chroma_size]` — U
2704///   (Cb) chroma plane at half horizontal + vertical resolution.
2705/// * `pixels[width * height + chroma_size .. width * height +
2706///   2 * chroma_size]` — V (Cr) chroma plane.
2707///
2708/// where `chroma_size = ceil(width / 2) * ceil(height / 2)`.
2709///
2710/// ## Accepted scope (round 409)
2711///
2712/// * `width`, `height` ∈ `[1, 16384]` per axis (r460: any extent — a
2713///   non-multiple-of-8 picture is padded to the mi grid internally and
2714///   coded under its true `frame_size`)
2715///   ([`crate::encoder::KEY_FRAME_MAX_DIM`]).
2716/// * 8-bit 4:2:0 YUV. Single KEY frame per stream (one IVF frame).
2717/// * `base_q_idx = 0` — the §5.9.2 `CodedLossless` arm. The matching
2718///   [`decode_av1`] invocation on the returned IVF bytes recovers
2719///   the input planes byte-for-byte (surfaced as
2720///   [`decoder::Frame::Spec`] — the stream rides the spec-faithful
2721///   decode path, as any conformant stream does).
2722///
2723/// Lossy quant is reachable through
2724/// [`crate::encoder::encode_key_frame_yuv420_with_q`] (decode ==
2725/// encoder reconstruction, bit-exact); monochrome + the historical
2726/// non-conformant mirror drivers stay on the crate-public
2727/// `encoder::*` entries.
2728///
2729/// ## Errors
2730///
2731/// * `pixels.len() != width * height + 2 * ceil(width / 2) * ceil(height / 2)`
2732///   ⇒ [`Error::PartitionWalkOutOfRange`].
2733/// * Dimensions out of `[1, 16384]` per axis ⇒
2734///   [`Error::PartitionWalkOutOfRange`].
2735/// * Internal partition-tree / coefficient writer overflow — same
2736///   `Error` variants the driver surfaces.
2737pub fn encode_av1(pixels: &[u8], width: u32, height: u32) -> Result<Vec<u8>, Error> {
2738    use crate::encoder::{encode_key_frame_yuv420, Yuv420Frame};
2739    let chroma_w = width.div_ceil(2) as usize;
2740    let chroma_h = height.div_ceil(2) as usize;
2741    let y_size = (width as usize) * (height as usize);
2742    let uv_size = chroma_w * chroma_h;
2743    let expected = y_size + 2 * uv_size;
2744    if pixels.len() != expected {
2745        return Err(Error::PartitionWalkOutOfRange);
2746    }
2747    let (y_bytes, rest) = pixels.split_at(y_size);
2748    let (u_bytes, v_bytes) = rest.split_at(uv_size);
2749    let frame = Yuv420Frame {
2750        width,
2751        height,
2752        y: y_bytes.to_vec(),
2753        u: u_bytes.to_vec(),
2754        v: v_bytes.to_vec(),
2755    };
2756    let encoded = encode_key_frame_yuv420(&frame)?;
2757    Ok(encoded.ivf_bytes)
2758}
2759
2760/// Codec registration entry point.
2761///
2762/// Installs the intra-only [`registry::Av1Decoder`] factory and claims
2763/// the ISOBMFF `av01` / IVF `AV01` FourCC and Matroska `V_AV1` container
2764/// identifiers, making the AV1 decoder reachable through the
2765/// `RuntimeContext` / `oxideav-meta::register_all` path. See
2766/// [`registry`] for the bridge details and the registered scope.
2767///
2768/// The historical direct API ([`decode_av1`] / [`encode_av1`]) is
2769/// unaffected and remains the primary surface for in-crate callers.
2770pub fn register(ctx: &mut RuntimeContext) {
2771    registry::register(ctx);
2772}
2773
2774oxideav_core::register!("av1", register);