1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
//! Encoder side of the crate.
//!
//! Arc 1 (round 206) landed the bit-output plumbing. Arc 2 (round
//! 207) lands the `frame_header_obu()` writer on top.
//!
//! Layers:
//!
//! * [`bitwriter::BitWriter`] — MSB-first bit-output buffer, the
//! inverse of [`crate::bitreader::BitReader`] (§8.1 `read_bit`),
//! plus `write_leb128()` (§4.10.5), `write_uvlc()` (§4.10.3),
//! `write_su(n)` (§4.10.6), and `write_ns(n)` (§4.10.7) — the
//! full descriptor-inverse set the §5.5 / §5.9 writers need.
//!
//! * [`obu`] — Open Bitstream Unit framer per §5.3. Writes the
//! §5.3.2 one-byte `obu_header`, the optional §5.3.3
//! `obu_extension_header`, and the optional `leb128()`
//! `obu_size` size field for the §5.2 low-overhead bytestream
//! format. Concatenation of multiple OBUs into a temporal unit
//! is byte-aligned and simply uses [`ObuWriter::write`] N times.
//!
//! * [`sequence_obu`] — `sequence_header_obu()` writer per §5.5.1
//! (with §5.5.2 `color_config`, §5.5.3 `timing_info`, §5.5.4
//! `decoder_model_info`, §5.5.5 `operating_parameters_info`).
//! The inverse of [`crate::sequence_header::parse_sequence_header`].
//! Reuses the same [`crate::sequence_header::SequenceHeader`]
//! struct as the source-of-truth descriptor, so a written
//! payload immediately round-trips through the parser.
//!
//! * [`frame_obu`] — `frame_header_obu()` writer per §5.9.1 /
//! §5.9.2 plus every sub-procedure §5.9.2 calls into. The
//! inverse of [`crate::frame_header::parse_frame_header`] on the
//! intra / show-existing-frame / reduced-still paths and on the
//! inter shared tail above `disable_frame_end_update_cdf`.
//! Reuses the parser's [`crate::frame_header::FrameHeader`] as
//! source-of-truth descriptor.
//!
//! * [`ivf`] — IVF v0 container writer (32-byte file header + 12-
//! byte per-frame header) for shipping the encoded OBU temporal
//! units into a playable file. IVF is a trivial public file
//! format developed for VP8 testing; the byte layout used here
//! matches the `.ivf` fixtures already in `docs/video/av1/
//! fixtures/`.
//!
//! * [`temporal_unit`] — arc 3 (round 208) glue. Wraps the per-OBU
//! body writers above with the §5.3.4 `trailing_bits()` trailer
//! and the §5.3.1 `obu_size` size field, then aggregates a
//! sequence of OBUs into a §7.5 temporal unit (TD prefix +
//! optional SH + the frame OBUs). The product is a complete
//! byte-aligned bytestream a downstream parser walks back via
//! [`crate::obu::ObuIter`].
//!
//! * [`tile_group_obu`] — arc 4 (round 210) §5.11.1 framing
//! skeleton on top of the r209 [`symbol_writer`]. Builds the
//! §5.11.1 `tile_group_obu` body around a caller-supplied
//! `Vec<TilePayload>` (each `TilePayload` is a finished
//! `SymbolWriter::finish()` byte run): writes
//! `tile_start_and_end_present_flag` / `tg_start` / `tg_end`,
//! byte-aligns, then per-tile `tile_size_minus_1`
//! (`le(TileSizeBytes)`) + tile bytes for every non-last tile.
//! The body is the byte-aligned payload `write_obu_with_size`
//! wraps in an `OBU_TILE_GROUP` (which §5.3.1 explicitly
//! excludes from the §5.3.4 trailer).
//!
//! * [`block_mode_info`] — arc 5 (round 211) per-block §5.11 syntax
//! writers, intra arm only: `write_skip` (§5.11.11),
//! `write_intra_segment_id` (§5.11.8 + §5.11.9), `write_intra_frame_y_mode`
//! (§5.11.7 line 13 with the §8.3.2 neighbour-CDF ctx),
//! `write_y_mode` (§5.11.22 line 3 with the `Size_Group[ MiSize ]`
//! ctx), and `write_intra_uv_mode` (§5.11.22 line 6 with the
//! §8.3.2 CFL-allowed selector). Pure stateless: ctx is
//! caller-supplied (mirroring [`SymbolWriter::write_symbol`]'s
//! caller-supplied CDF slice pattern); round-trip tests drive the
//! output back through the matching `PartitionWalker::decode_*`
//! methods.
//!
//! * [`coefficients`] — arc 6 (round 212) first slice of the §5.11.39
//! `coefficients()` writers: `write_txb_skip` (the `all_zero` S()),
//! `write_eob_pt` (eob_pt_{16..1024} S() + eob_extra S() +
//! eob_extra_bit L(1) refinement loop) and `write_dc_sign` (the
//! `c == 0` forward-scan S()). Arc 7 (round 213) extends with the
//! per-coefficient base-level chain: `write_coeff_base_eob` (the
//! 3-symbol §9.4 alphabet at `c == eob - 1`), `write_coeff_base`
//! (the 4-symbol alphabet at non-EOB positions) and `write_coeff_br`
//! (one `BR_CDF_SIZE`-symbol §9.4 alphabet S() per `coeff_br` chain
//! iteration, capped at `COEFF_BASE_RANGE / (BR_CDF_SIZE - 1) = 4`
//! repetitions by the spec's `if (coeff_br < BR_CDF_SIZE - 1) break`
//! guard). Same stateless surface as `block_mode_info`; the §8.3.2
//! ctx values are caller-supplied — the existing decoder helpers
//! [`crate::cdf::get_coeff_base_ctx`] /
//! [`crate::cdf::get_coeff_base_eob_ctx`] /
//! [`crate::cdf::get_br_ctx`] derive them from the running `Quant[]`
//! array on both sides.
//!
//! Arc 8 (round 214) landed the `golomb_length_bit` / `golomb_data_bit`
//! magnitude tail (§5.11.39 lines 84-93) for coefficient magnitudes
//! above `NUM_BASE_LEVELS + COEFF_BASE_RANGE = 14`, with the
//! §6.10.34 `length <= 20` conformance bound enforced as a caller-bug
//! reject.
//!
//! Arc 10 (round 216) lands the §5.11.4 [`partition`] decision-tree
//! **symbol writer**: the inverse of the `partition` / `split_or_horz`
//! / `split_or_vert` S() reads inside
//! [`crate::cdf::PartitionWalker::decode_partition`]. Encoder drivers
//! pick a partition ordinal from their RD search, call
//! [`partition::write_partition`] with the chosen partition + the same
//! (`has_rows`, `has_cols`, `ctx`) the decoder will derive on its
//! recursive walk, then recurse on the appropriate `subSize` children.
//! Two predicate helpers ([`partition::partition_none_only`] /
//! [`partition::partition_split_only`]) surface the §5.11.4 first /
//! last conditional so the driver knows when to skip the writer call.
//!
//! Arc 11 (round 217) lands the §5.11.4 recursive **dispatch driver**:
//! [`partition_tree::write_partition_tree`] composes the r211–r216 per-block
//! writers (`write_skip`, `write_intra_segment_id`, `write_y_mode`,
//! `write_intra_uv_mode`, per-plane `write_coefficients`) together with the
//! r216 `write_partition` symbol writer into a complete intra-arm
//! partition-tree walker driven from a caller-supplied
//! [`partition_tree::EncodeNode`] tree. The driver maintains its own
//! `MiSizes[]` grid so the §8.3.2 `partition_ctx_for` lookup observes the
//! same neighbour widths the decoder's parallel
//! [`crate::cdf::PartitionWalker`] observes. Round-trips a leaf or 7-leaf
//! two-level split tree back through `decode_partition` plus manual
//! `decode_block` replay; the encoder is now a true encoder end-to-end
//! for the intra-only path.
//!
//! Arc 12 (round 218) lands the §5.11.36 transform_tree / tx_size
//! **writers**: [`transform_tree::write_block_tx_size`] (the §5.11.15
//! `tx_depth` symbol for the §5.11.16 `else` arm — inverse of
//! [`crate::cdf::PartitionWalker::read_block_tx_size`]) and
//! [`transform_tree::write_var_tx_size`] (the §5.11.17 recursive
//! `txfm_split` chain — inverse of
//! [`crate::cdf::PartitionWalker::read_var_tx_size`]). The
//! variable-transform writer takes a caller-supplied
//! [`transform_tree::VarTxNode`] tree describing the desired
//! `(txfm_split, sub_tx_size)` decisions per node, mirroring the same
//! Leaf/Split shape already used for the §5.11.4 `partition_tree`
//! dispatch.
//!
//! Arc 13 (round 219) bootstraps the **pixel-space encoder** with the
//! forward 4×4 DCT primitive in [`forward_transform`]: 1D
//! [`forward_transform::forward_dct_4`] and 2D
//! [`forward_transform::forward_dct_4x4`]. The kernel is the matrix
//! transpose of the §7.13.2.3 inverse DCT-4 reproduced in
//! [`crate::transform::inverse_dct`] (`n = 2` branch). Round-trip
//! lockstep against the inverse confirms `M^T · M ≈ 2 · I` (exactly
//! diagonal; `≈ 1.99988` on even rows and `≈ 1.99994` on odd rows
//! because the AV1 cosine constants are integer-rounded approximations
//! of the analytic values). The off-diagonal entries are exactly zero
//! — the basis is mutually orthogonal. This primitive is the bridge
//! between the arc-1..12 syntax-only encoder (consumes pre-decided
//! `Quant[]`) and a real encoder that takes pixel residuals as input.
//!
//! Arc 14 (round 220) lands the **forward quantization primitive** —
//! [`forward_quantize::forward_quantize`], the encoder counterpart of
//! [`crate::cdf::dequantize_step1`]. Consumes a post-forward-transform
//! coefficient buffer, the per-frame [`crate::cdf::QuantizerParams`],
//! and the per-block plane / segment / tx-type / qm-level selectors;
//! returns the dense `Tx_Width * Tx_Height` `Quant[]` array the
//! §5.11.39 `coefficients()` writer consumes. Round-half-away-from-
//! zero inversion of the spec's `(|dq| & 0xFF_FFFF) / dqDenom`
//! truncating divide; bit-exact roundtrip on the lossless
//! `q_index = 0` lattice and within one quantization step elsewhere.
//!
//! Arc 17 (round 223) extends the pixel driver to **4:2:0 YUV input**
//! via the (r428-retired) mirror pixel driver. The chroma walk mirrors
//! the luma side: DC_PRED from the running reconstructed chroma plane,
//! forward WHT (lossless arm), forward quantize, write_coefficients per
//! plane. Per §5.11.5 `HasChroma` at 4:2:0 / BLOCK_4X4 the chroma
//! coefficient pass fires only on luma cells `(1,1), (1,3), (3,1),
//! (3,3)` (the SE corner of each 8×8 luma quadrant), so each chroma
//! 4×4 block is emitted exactly once. The same `(SequenceHeader,
//! FrameHeader)` pair feeds both Y-only and YUV entry points — the
//! tiny-i-only-16x16-prof0 fixture is `monochrome = false` /
//! subsampling_x = subsampling_y = 1 already. Every chroma plane
//! round-trips pixel-for-pixel at `base_q_idx = 0` on arbitrary
//! inputs (lossless WHT chain).
//!
//! Arc 16 (round 222) lands the **forward 4×4 Walsh-Hadamard transform**
//! in [`forward_wht`]: 1D [`forward_wht::forward_wht4`] and 2D
//! [`forward_wht::forward_wht_4x4`]. Derived clean-room by inverting
//! the §7.13.2.10 inverse-WHT body algebraically (the four output cells
//! determine `A = a + b` and `D = d - c` uniquely; the `(A - D) >> 1`
//! halving is shared between forward and inverse so the round-trip is
//! exact regardless of parity). Unlike the integer-approximated DCT,
//! the WHT is a **pure integer butterfly** ⇒ **bit-exact round-trip
//! for any integer input**. The (r428-retired) mirror pixel driver then
//! routes through the forward WHT on the §5.9.2 `CodedLossless` arm
//! (`base_q_idx == 0 && DeltaQ?? all zero`), unlocking pixel-perfect
//! roundtrip on arbitrary inputs at `base_q_idx = 0`.
//!
//! Arc 19 (round 226) lands the **forward ADST / FLIPADST / IDTX**
//! primitives in [`forward_adst`] and [`forward_identity`]. Same
//! matrix-cache recipe as r225's forward DCT: the §7.13.2.6/7/8
//! inverse ADST is a fixed integer linear map for `n in 2..=4` and
//! the §7.13.2.11..§7.13.2.14 inverse identity is a per-cell scalar
//! map for `n in 2..=5`; the forward kernels are the algebraic
//! transposes (matrix transpose for ADST, scalar transpose-=-self
//! for the diagonal IDTX). FLIPADST reuses the ADST kernel and
//! applies the involutory reverse on the residual input — per
//! §7.13.3 the flip is purely a coordinate transform on the frame-
//! buffer write, NOT a separate butterfly. This rounds out the menu
//! of forward 1D/2D primitives the encoder needs to consider when
//! picking `tx_type` per block; the §7.13.3-equivalent forward 2D
//! dispatcher with row-/col-shift envelope is the next arc.
//!
//! Arc 20 (round 227) lands the **§7.13.3-equivalent forward 2D
//! transform dispatcher** in [`forward_transform_2d`]:
//! [`forward_transform_2d::forward_transform_2d`] consumes a row-
//! major spatial residual buffer + `(tx_size, plane_tx_type,
//! lossless)` and returns the row-major coefficient buffer the
//! decoder's [`crate::transform::inverse_transform_2d`] would
//! consume. Composes the r219/r222/r225/r226 per-axis forward
//! kernels (DCT / ADST / FLIPADST / IDTX / WHT) into the §7.13.3
//! column-then-row pipeline (transpose of the decoder's row-then-
//! column composition), with the §7.13.3 `colShift` / `rowShift`
//! shift envelope applied as **pre-scales** (`<< colShift` before
//! the column pass, `<< rowShift` before the row pass) so the
//! decoder's `Round2(_, shift)` post-scales cancel exactly. Square
//! sizes only this arc (`TX_4X4`, `TX_8X8`, `TX_16X16`, `TX_32X32`,
//! `TX_64X64`); rectangular sizes (`TX_4X8`, …, `TX_64X16`) deferred
//! to a subsequent arc.
//!
//! Round-trip validation: lossless `TX_4X4` arm is **bit-exact** on
//! arbitrary integer inputs (WHT chain). Lossy arms recover the
//! input scaled by the analytic per-axis kernel norms (DCT-N ≈ N,
//! ADST-N ≈ N/2, IDTX with §7.13.2.11..14 scalars) within a
//! conservative per-cell rounding bound. FLIPADST family pre-flips
//! the spatial residual along the appropriate axis (§7.12.3 step-3
//! mirror) before the plain ADST kernel runs.
//!
//! Next arc: pixel-driver chroma path (needs frame-header build with
//! `monochrome = false`). The `|log2W - log2H| == 1` family was
//! landed across r235 / r238 / r241 / r244 (`TX_4X8` / `TX_8X4` /
//! `TX_8X16` / `TX_16X8` / `TX_16X32` / `TX_32X16` / `TX_32X64` /
//! `TX_64X32`); the `|log2W - log2H| == 2` family was landed across
//! r250 / r251 / r252 (`TX_16X64` / `TX_64X16` / `TX_4X16` /
//! `TX_16X4` / `TX_8X32` / `TX_32X8`) — all twelve §5.11
//! `TX_SIZES_ALL` rectangular shapes are now dispatcher-supported.
//! Standalone `decode_av1` entry that wires the existing decoder
//! modules into a full pipeline. §5.11.18 inter-arm `mode_info()`
//! dispatcher; intra angle / palette encode. §5.9.7
//! `frame_size_with_refs()` inverse + §5.9.24 `read_global_param`
//! signed-subexp inverse for the remaining inter-frame paths.
// internal — exposed for tests/fuzz; not part of the stable API
pub
pub
pub
pub
pub
pub
/// r460 — the still-picture entry point (AVIF / HEIF `av01` items).
pub
pub
pub use BitWriter;
pub use ;
// r430 — §7.3 large-scale-tile camera-frame write arm (single-tile
// camera frames; the tile-list assembly lives in
// [`crate::tile_list`]).
pub use ;
pub use ;
pub use ;
pub use ;
pub use forward_quantize;
pub use ;
pub use forward_transform_2d;
pub use ;
pub use write_frame_header_obu;
pub use encode_gop_yuv420_with_q_seg_rate_model;
pub use encode_gop_yuv420_with_q_seg_rate_model_gm;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use encode_key_frame_yuv420_with_q_rate_model;
pub use ;
pub use ;
// r431 — §5.9.15 multi-tile write arm (uniform tile layouts,
// explicitly configured; `(0, 0)` reproduces the single-tile stream
// byte for byte).
pub use ;
pub use ;
pub use ;
// r431 — KEY-frame §5.9.17 delta-q A/B hook (hidden).
pub use encode_key_frame_yuv420_with_q_dq;
pub use ;
pub use ;
pub use ;
pub use ;
// r428 — the encoder-mirror emit arms are retired (see the r428
// CHANGELOG entry); the shared frame/sequence scaffolding they
// housed lives in [`yuv_frame`] now.
pub use Yuv420Frame;
pub use ;
// r421 — rate-model selector, exposed (hidden) so the sweep harnesses
// can A/B the twin-priced elections against the heuristic baseline.
pub use encode_pyramid_gop_yuv420_with_q_rate_model;
pub use ;
pub use ;
// r424 — deep-pyramid / adaptive-mini-GOP tuning surfaces, exposed
// (hidden) for the measurement harnesses.
pub use ;
pub use ;
pub use RateModel;
// r430 — temporally scalable GOP arm (§6.7.5 operating points +
// §5.3.3 extension headers on the wire).
pub use ;
// r433 — tiled scalable-ladder siblings.
pub use ;
// r431 — spatially scalable arm: independently-coded spatial layers,
// spatial_id extension headers, nested §6.7.5 operating points.
pub use ;
// r436 — per-layer tile layouts + tile-group packaging on the
// spatial-SVC driver.
pub use ;
pub use write_sequence_header_obu;
pub use ;
pub use SymbolWriter;
pub use ;
pub use ;
pub use ;
pub use ;