code wiki / _hdl_build / nx_rd_intra_gate.nx

nx_rd_intra_gate.nx source

↩ module page · 70 lines · 4250 B

1// nx_rd_intra_gate.nx -- MEASURES the rate-distortion gain of intra prediction: code one structured frame two ways 2// (naive pixels-128 vs neighbour-predicted, raster order) at the same QP and compare bytes + PSNR. Proves V-R7 3// shifts the RD curve left (fewer bytes at equal quality). Composes nx_intra+nx_vtransform+nx_ventropy+nx_quality_metric. 4import "nx_syscalls.nx" 5import "nx_gate_emit_lib.nx" 6import "nx_intra.nx" 7import "nx_vtransform.nx" 8import "nx_ventropy.nx" 9import "nx_quality_metric.nx" 10import "nx_gate_verdict.nx" 11 12func code_frame(orig: *u8, recon: *u8, W: i64, H: i64, qp: i64, use_pred: i64, ebuf: *u8, blk: *i64, pred: *i64, top: *i64, left: *i64) -> i64 { 13 var bits: i64 = 0 14 var by: i64 = 0 15 while by < H/4 { 16 var bx: i64 = 0 17 while bx < W/4 { 18 let cx: i64 = bx*4; let cy: i64 = by*4 19 var ht: i64 = 0; var hl: i64 = 0 20 if use_pred == 1 { 21 if cy > 0 { ht = 1; var x: i64=0; while x<4 { top[x] = recon[(cy-1)*W + (cx+x)] as i64; x=x+1 } } 22 if cx > 0 { hl = 1; var y: i64=0; while y<4 { left[y] = recon[(cy+y)*W + (cx-1)] as i64; y=y+1 } } 23 } 24 // load block pixels 25 let src: *i64 = sys_mmap(16*8) as *i64 26 var yy: i64=0; while yy<4 { var xx: i64=0; while xx<4 { src[yy*4+xx] = orig[(cy+yy)*W+(cx+xx)] as i64; xx=xx+1 } yy=yy+1 } 27 if use_pred == 1 { in_best(src, top, left, ht, hl, pred) } else { var i: i64=0; while i<16 { pred[i]=128; i=i+1 } } 28 // residual -> transform -> quant -> entropy ; then reconstruct 29 var i2: i64=0; while i2<16 { blk[i2] = src[i2] - pred[i2]; i2=i2+1 } 30 vt_fwd(blk); vt_quant(blk, qp) 31 bits = bits + ve_encode(blk, ebuf) 32 vt_dequant(blk, qp); vt_inv(blk) 33 yy=0; while yy<4 { var xx: i64=0; while xx<4 { var v: i64 = pred[yy*4+xx] + blk[yy*4+xx]; if v<0 {v=0} if v>255 {v=255} recon[(cy+yy)*W+(cx+xx)] = v as u8; xx=xx+1 } yy=yy+1 } 34 bx = bx + 1 35 } 36 by = by + 1 37 } 38 return bits 39} 40 41func main() -> i64 { 42 g_puts("nx_rd_intra gate (RD gain from intra prediction, MEASURED)\n" as *u8) 43 var pass: i64 = 0; var total: i64 = 0 44 let W: i64 = 32; let H: i64 = 32; let n: i64 = W*H; let QP: i64 = 12 45 let orig: *u8 = sys_mmap(n); let rN: *u8 = sys_mmap(n); let rP: *u8 = sys_mmap(n) 46 let ebuf: *u8 = sys_mmap(256); let blk: *i64 = sys_mmap(16*8) as *i64; let pred: *i64 = sys_mmap(16*8) as *i64 47 let top: *i64 = sys_mmap(4*8) as *i64; let left: *i64 = sys_mmap(4*8) as *i64 48 // a structured frame: vertical stripes (varies with x, constant down columns) -> intra VERTICAL predicts it well 49 var y: i64=0; while y<H { var x: i64=0; while x<W { orig[y*W+x] = (50 + x*5) as u8; x=x+1 } y=y+1 } 50 51 let naive_bits: i64 = code_frame(orig, rN, W, H, QP, 0, ebuf, blk, pred, top, left) 52 let pred_bits: i64 = code_frame(orig, rP, W, H, QP, 1, ebuf, blk, pred, top, left) 53 let nb: i64 = (naive_bits+7)/8; let pb: i64 = (pred_bits+7)/8 54 let np: i64 = qm_psnr_cdb(orig, rN, n); let pp: i64 = qm_psnr_cdb(orig, rP, n) 55 g_puts(" [measure] naive: " as *u8); g_pn(nb); g_puts(" B @ PSNR " as *u8); g_pn(np); g_puts(" intra-pred: " as *u8); g_pn(pb); g_puts(" B @ PSNR " as *u8); g_pn(pp); g_puts("\n" as *u8) 56 57 pass = pass + g_check("intra prediction uses FEWER bytes at >= the quality (RD curve shifts left)" as *u8, (pb < nb) & (pp >= np - 50)); total=total+1 58 pass = pass + g_check("both reconstruct (PSNR sane)" as *u8, (np > 2000) & (pp > 2000)); total=total+1 59 60 g_puts("---- rd-intra gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 61 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 62 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 63 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 64 let ctr__dry: *i64 = gv_ctr() 65 ctr__dry[0] = pass 66 ctr__dry[1] = total 67 let rc__dry: i64 = gv_verdict("RD-INTRA-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 68 sys_exit(rc__dry) 69 return rc__dry 70}