nx_intra_pred.nx source
↩ module page · 68 lines · 3178 B
1// nx_intra_pred.nx -- sovereign directional intra prediction for 4x4 luma blocks (DC / vertical / horizontal /
2// diagonal-down-right), predicting from already-available neighbor samples (top row, left column, top-left corner),
3// exactly as H.264/AVC intra-4x4 does. The codec is intra-DC-only today; this is the lever to close the measured
4// real-content efficiency gap (RT-003 R1b). Built as a reusable lib so the codec's intra path can adopt it, and so
5// nx_intra_pred_gate can MEASURE the residual reduction on a real frame before any core-codec change. No syscalls here.
6
7const IP_DC: i64 = 0
8const IP_V: i64 = 1
9const IP_H: i64 = 2
10const IP_DDR: i64 = 3
11const IP_NMODES: i64 = 4
12
13func ip_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
14
15// Predict a 4x4 block at pixel (px,py) in a W-wide image into pred[0..15] (row-major) using `mode`.
16// Requires px>=1 and py>=1 (top row + left col + corner exist). src is the sample plane the predictor reads from
17// (reconstructed neighbors in a real codec; the measurement may pass originals as an upper-bound proxy).
18func ip_predict4(src: *u8, W: i64, px: i64, py: i64, mode: i64, pred: *u8) -> i64 {
19 if mode == IP_DC {
20 var s: i64 = 0; var i: i64 = 0
21 while i < 4 { s = s + (src[(py-1)*W+px+i] as i64) + (src[(py+i)*W+px-1] as i64); i = i + 1 }
22 let dc: i64 = (s + 4) / 8
23 var y: i64 = 0; while y < 4 { var x: i64 = 0; while x < 4 { pred[y*4+x] = dc as u8; x = x + 1 } y = y + 1 }
24 return 0
25 }
26 if mode == IP_V {
27 var y: i64 = 0
28 while y < 4 { var x: i64 = 0; while x < 4 { pred[y*4+x] = src[(py-1)*W+px+x]; x = x + 1 } y = y + 1 }
29 return 0
30 }
31 if mode == IP_H {
32 var y: i64 = 0
33 while y < 4 { var x: i64 = 0; while x < 4 { pred[y*4+x] = src[(py+y)*W+px-1]; x = x + 1 } y = y + 1 }
34 return 0
35 }
36 // IP_DDR -- diagonal down-right: above-left edges propagate along 45-degree diagonals.
37 let corner: i64 = src[(py-1)*W+px-1] as i64
38 var y: i64 = 0
39 while y < 4 { var x: i64 = 0
40 while x < 4 {
41 var p: i64 = corner
42 if x > y { p = src[(py-1)*W+px+(x-y-1)] as i64 }
43 if x < y { p = src[(py+(y-x-1))*W+px-1] as i64 }
44 pred[y*4+x] = p as u8
45 x = x + 1 } y = y + 1 }
46 return 0
47}
48
49// Sum of absolute residual for the 4x4 block at (px,py) vs a prediction (a proxy for the bits the residual will cost).
50func ip_sad4(src: *u8, W: i64, px: i64, py: i64, pred: *u8) -> i64 {
51 var s: i64 = 0; var y: i64 = 0
52 while y < 4 { var x: i64 = 0
53 while x < 4 { s = s + ip_abs((src[(py+y)*W+px+x] as i64) - (pred[y*4+x] as i64)); x = x + 1 } y = y + 1 }
54 return s
55}
56
57// Choose the lowest-SAD mode for a 4x4 block; returns the min SAD and writes the chosen mode to outmode[0].
58func ip_best4(src: *u8, W: i64, px: i64, py: i64, pred: *u8, outmode: *i64) -> i64 {
59 var best: i64 = 0x7fffffff; var bm: i64 = 0; var m: i64 = 0
60 while m < IP_NMODES {
61 ip_predict4(src, W, px, py, m, pred)
62 let s: i64 = ip_sad4(src, W, px, py, pred)
63 if s < best { best = s; bm = m }
64 m = m + 1
65 }
66 outmode[0] = bm
67 return best
68}