code wiki / (root) / nx_intra_pred.nx

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}