code wiki / _hdl_build / nx_rd_intra_gate.nx

nx_rd_intra_gate.nx source

↩ module page · 62 lines · 3808 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" 10 11func 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 { 12 var bits: i64 = 0 13 var by: i64 = 0 14 while by < H/4 { 15 var bx: i64 = 0 16 while bx < W/4 { 17 let cx: i64 = bx*4; let cy: i64 = by*4 18 var ht: i64 = 0; var hl: i64 = 0 19 if use_pred == 1 { 20 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 } } 21 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 } } 22 } 23 // load block pixels 24 let src: *i64 = sys_mmap(16*8) as *i64 25 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 } 26 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 } } 27 // residual -> transform -> quant -> entropy ; then reconstruct 28 var i2: i64=0; while i2<16 { blk[i2] = src[i2] - pred[i2]; i2=i2+1 } 29 vt_fwd(blk); vt_quant(blk, qp) 30 bits = bits + ve_encode(blk, ebuf) 31 vt_dequant(blk, qp); vt_inv(blk) 32 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 } 33 bx = bx + 1 34 } 35 by = by + 1 36 } 37 return bits 38} 39 40func main() -> i64 { 41 g_puts("nx_rd_intra gate (RD gain from intra prediction, MEASURED)\n" as *u8) 42 var pass: i64 = 0; var total: i64 = 0 43 let W: i64 = 32; let H: i64 = 32; let n: i64 = W*H; let QP: i64 = 12 44 let orig: *u8 = sys_mmap(n); let rN: *u8 = sys_mmap(n); let rP: *u8 = sys_mmap(n) 45 let ebuf: *u8 = sys_mmap(256); let blk: *i64 = sys_mmap(16*8) as *i64; let pred: *i64 = sys_mmap(16*8) as *i64 46 let top: *i64 = sys_mmap(4*8) as *i64; let left: *i64 = sys_mmap(4*8) as *i64 47 // a structured frame: vertical stripes (varies with x, constant down columns) -> intra VERTICAL predicts it well 48 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 } 49 50 let naive_bits: i64 = code_frame(orig, rN, W, H, QP, 0, ebuf, blk, pred, top, left) 51 let pred_bits: i64 = code_frame(orig, rP, W, H, QP, 1, ebuf, blk, pred, top, left) 52 let nb: i64 = (naive_bits+7)/8; let pb: i64 = (pred_bits+7)/8 53 let np: i64 = qm_psnr_cdb(orig, rN, n); let pp: i64 = qm_psnr_cdb(orig, rP, n) 54 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) 55 56 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 57 pass = pass + g_check("both reconstruct (PSNR sane)" as *u8, (np > 2000) & (pp > 2000)); total=total+1 58 59 g_puts("---- rd-intra gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 60 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 61 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 62}