nx_av1_intra.nx
buildroot/runtime/nx_av1_intra.nx
about
nx_av1_intra.nx -- AV1/AV2 non-directional intra prediction.
Part of the residual path: before any coefficient is added, a block is
PREDICTED from its already-decoded above row and left column. These are the
modes that need no angle -- DC, vertical, horizontal, Paeth and the three
smooth variants -- and together they cover most real intra blocks.
AVAILABILITY CHANGES THE FORMULA, NOT JUST THE INPUT. DC has FOUR distinct
cases: both edges present, only above, only left, and neither. With neither
it is not zero and not an average of nothing -- it is the mid-grey
1 << (bitdepth - 1). A decoder that treats a missing edge as zeros predicts
black along the top and left of every frame, which looks like a vignette
rather than a bug.
THE SMOOTH WEIGHTS SUM TO 256, NOT 255. Each smooth predictor blends a
weight w against (256 - w) and rounds with +128 >> 8 (or +256 >> 9 for the
two-axis form). Using 255 as the complement makes constant input predict
slightly-wrong constant output -- a fraction of a level per pixel, which
accumulates across a frame of intra blocks and shows as a gradient.
PAETH PICKS, IT DOES NOT AVERAGE. It selects whichever of left, above or
above-left is nearest the linear estimate. The tie order matters: left
beats above, and above beats above-left.
EVERY LOCAL IS DECLARED ONCE. nx_cc uses FLAT FUNCTION SCOPE -- re-declaring
a name inside a sibling branch desyncs its parser (proven here 2026-07-31:
a `let below` in two exclusive branches produced 'unexpected operator token
at expression start'). Params also travel in an array rather than as ten
positional arguments.
genealogy_id: av1_spec_7_11_2_intra_prediction
lineage_id: nx_av1_intra_v1
license_tier: ORIGINAL
dependencies 1 imports · 1 importers
imports: nx_syscalls.nx
imported by: nx_av1_intra_gate.nx
structs
| none |
consts
| 37 | const NX_INTRA_DC: i64 = 0 |
| 38 | const NX_INTRA_V: i64 = 1 |
| 39 | const NX_INTRA_H: i64 = 2 |
| 40 | const NX_INTRA_PAETH: i64 = 3 |
| 41 | const NX_INTRA_SMOOTH: i64 = 4 |
| 42 | const NX_INTRA_SMOOTH_V: i64 = 5 |
| 43 | const NX_INTRA_SMOOTH_H: i64 = 6 |
| 45 | const NX_INTRA_P_ABOVELEFT: i64 = 0 |
| 46 | const NX_INTRA_P_W: i64 = 1 |
| 47 | const NX_INTRA_P_H: i64 = 2 |
| 48 | const NX_INTRA_P_HAVE_A: i64 = 3 |
| 49 | const NX_INTRA_P_HAVE_L: i64 = 4 |
| 50 | const NX_INTRA_P_BITDEPTH: i64 = 5 |
functions
| 52 | func nx_intra_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } called by 1: nx_intra_paeth_pick |
| 54 | func nx_intra_sm_weight(size: i64, i: i64) -> i64 |
| 94 | func nx_intra_dc_value(above: *i64, left: *i64, p: *i64) -> i64 |
| 124 | func nx_intra_paeth_pick(left: i64, above: i64, aboveleft: i64) -> i64 |
| 136 | func nx_intra_predict(mode: i64, out: *i64, above: *i64, left: *i64, p: *i64) -> i64 |