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);