code wiki / _hdl_build / nx_vcodec_t8_gate.nx

nx_vcodec_t8_gate.nx source

↩ module page · 182 lines · 10866 B

1import "nx_gate_base.nx" 2// nx_vcodec_t8_gate.nx -- PER-MB VARIABLE TRANSFORM SIZE proof (task #46 rung 2, the HEVC-jump integration 3// validated by nx_vcodec_tsize_rd_gate: 8x8 DCT = 44-75% fewer bytes at matched PSNR on flat content). 4// Proves, at the WIRE level (vv_*: 3 planes + AQ + quarter-pel + deblock): 5// (1) CAVLC t8 frames decode BIT-EXACT across a 5-frame key+P chain of mixed flat/textured/moving content 6// (2) RANGE-CODED t8 frames (rct8) decode BIT-EXACT across the same chain (rc_block64 contexts in sync) 7// (3) RD on a FLAT-heavy keyframe: t8 strictly fewer bytes than the 4x4 baseline at PSNR within 1 dB 8// (4) rct8 strictly smaller than rc (the 8x8 win STACKS on the range coder's 36%) 9// Textured + chain totals reported honestly (textured MBs stay 4x4 by policy -> expect ~parity there). 10// license_tier: ORIGINAL 11import "nx_syscalls.nx" 12import "nx_video_codec_wasm.nx" 13 14func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 15" as *u8); return ok } 16func gn(v: i64) -> i64 { 17 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 18 let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} 19 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 20func eqb(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if (a[i]&0xff)!=(b[i]&0xff) { return 0 } i=i+1 } return 1 } 21func cpb(d: *u8, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[i]=s[i]; i=i+1 } return 0 } 22func sseL(a: *u8, b: *u8, n: i64) -> i64 { var s: i64=0; var i: i64=0; while i<n { let d: i64=(a[i]&0xff)-(b[i]&0xff); s=s+d*d; i=i+1 } return s } 23// integer PSNR in whole dB (10*log10(255^2/mse)); no else-if chains (nx parser) 24func psnrdb(sse: i64, npix: i64) -> i64 { 25 if sse<=0 { return 99 } 26 let mse: i64 = (sse*100)/npix 27 var num: i64 = 6502500*100; var m: i64 = mse; if m<1 {m=1} 28 var ratio: i64 = num/m 29 var db: i64 = 0; var t: i64 = ratio 30 while t >= 100 { db=db+10; t=t/10 } 31 var fr: i64 = 0 32 if t>=13 { fr=1 } if t>=16 { fr=2 } if t>=20 { fr=3 } if t>=25 { fr=4 } 33 if t>=32 { fr=5 } if t>=40 { fr=6 } if t>=50 { fr=7 } if t>=63 { fr=8 } if t>=79 { fr=9 } 34 return db + fr } 35 36// FLAT: gentle gradients everywhere (wall/skin class) -> AQ lv0/1 -> t8 fires on ~every MB 37func fill_flat(yuv: *u8, W: i64, H: i64) -> i64 { 38 let N: i64=W*H; let C2: i64=(W/2)*(H/2) 39 var r: i64=0 40 while r<H { var c: i64=0 41 while c<W { yuv[r*W+c]=(110 + (c+r)/5) as u8; c=c+1 } r=r+1 } 42 var i: i64=0 43 while i<C2 { let cr: i64=i/(W/2); let cc: i64=i%(W/2) 44 yuv[N+i]=(116 + (cc+cr)/16) as u8; yuv[N+C2+i]=(126 + cc/16) as u8; i=i+1 } 45 return 0 } 46// TEXTURED: high-frequency everywhere -> AQ lv2/3 -> t8 stays OFF by policy (4x4 kept) 47func fill_tex(yuv: *u8, W: i64, H: i64) -> i64 { 48 let N: i64=W*H; let C2: i64=(W/2)*(H/2) 49 var r: i64=0 50 while r<H { var c: i64=0 51 while c<W { var v: i64=128 + ((c*7+r*5)%37)*4 - 74; if v<0{v=0} if v>255{v=255}; yuv[r*W+c]=v as u8; c=c+1 } r=r+1 } 52 var i: i64=0 53 while i<C2 { let cr: i64=i/(W/2); let cc: i64=i%(W/2) 54 var u: i64=128 + ((cc*5+cr*3)%29)*3 - 42; if u<0{u=0} if u>255{u=255} 55 yuv[N+i]=u as u8; yuv[N+C2+i]=u as u8; i=i+1 } 56 return 0 } 57// MIXED + MOTION: gradient background with a textured square moving (2,1)/frame -> every MB class + inter 58func fill_mix(yuv: *u8, W: i64, H: i64, sh: i64) -> i64 { 59 let N: i64=W*H; let C2: i64=(W/2)*(H/2) 60 let bx: i64 = 48 + sh*2 61 let by2: i64 = 32 + sh 62 var r: i64=0 63 while r<H { var c: i64=0 64 while c<W { 65 var v: i64 = 100 + (c+r)/4 66 if c>=bx { if c<bx+64 { if r>=by2 { if r<by2+48 { v = 128 + ((c*7+r*5)%37)*4 - 74 } } } } 67 if v<0{v=0} if v>255{v=255} 68 yuv[r*W+c]=v as u8; c=c+1 } r=r+1 } 69 var i: i64=0 70 while i<C2 { let cr: i64=i/(W/2); let cc: i64=i%(W/2) 71 var u: i64 = 118 + (cc+sh)/8; if u>255{u=255} 72 yuv[N+i]=u as u8; yuv[N+C2+i]=(132 - cr/8) as u8; i=i+1 } 73 return 0 } 74 75// re-seed the rctx before EVERY enc/dec call (the rct8 decoder repoints rctx[3] into the wire buffer) 76func seedctx(rctx: *i64, emode: i64, est: *i64, probs: *i64, rcbuf: *u8, t8c: *i64) -> i64 { 77 rctx[0]=emode; rctx[1]=est as i64; rctx[2]=probs as i64; rctx[3]=rcbuf as i64; rctx[4]=t8c as i64; return 0 } 78 79// 5-frame key+P chain, mixed moving content; emode 0 = vv_enc_t8/vv_dec_t8, 1 = vv_enc_rct8/vv_dec_rct8. 80// Chains enc and dec prevs INDEPENDENTLY (the honest drift test). Adds 1 to t[0] per frame, p[0] on match. 81// Writes total t8 bytes to sums[0] and total 4x4-baseline (vv_enc / vv_enc_rc at same emode) to sums[1]. 82func run_chain(W: i64, H: i64, qp: i64, emode: i64, p: *i64, t: *i64, sums: *i64) -> i64 { 83 let N: i64=W*H; let C2: i64=(W/2)*(H/2); let sz: i64=N+2*C2 84 let cur: *u8=sys_mmap(sz) 85 let prevC: *u8=sys_mmap(sz); let reconC: *u8=sys_mmap(sz) 86 let prevT: *u8=sys_mmap(sz); let reconT: *u8=sys_mmap(sz) 87 let prevD: *u8=sys_mmap(sz); let reconD: *u8=sys_mmap(sz) 88 let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 89 let outC: *u8=sys_mmap(262144); let outT: *u8=sys_mmap(262144) 90 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(262144) 91 let rctx: *i64=sys_mmap(8*8) as *i64 92 let t8c: *i64=sys_mmap(5120) as *i64 93 vc_t8_init(t8c) 94 sums[0]=0; sums[1]=0 95 var f: i64=0 96 while f < 5 { 97 fill_mix(cur, W, H, f) 98 var key: i64=0; if f==0 { key=1 } 99 // 4x4 baseline at the same entropy mode (honest same-entropy comparison) 100 var cb: i64=0 101 if emode==1 { seedctx(rctx, 1, est, probs, rcbuf, t8c) 102 cb = vv_enc_rc(cur, prevC, reconC, W, H, qp, key, 6016, outC, 262144, blk, mv, rctx) } 103 else { cb = vv_enc(cur, prevC, reconC, W, H, qp, key, 6016, outC, 262144, blk, mv) } 104 // t8 encode + decode + bit-exact assert 105 seedctx(rctx, emode, est, probs, rcbuf, t8c) 106 var tb: i64=0 107 if emode==1 { tb = vv_enc_rct8(cur, prevT, reconT, W, H, qp, key, 6016, outT, 262144, blk, mv, rctx) } 108 else { tb = vv_enc_t8(cur, prevT, reconT, W, H, qp, key, 6016, outT, 262144, blk, mv, rctx) } 109 t[0]=t[0]+1 110 if tb > 0 { 111 seedctx(rctx, emode, est, probs, rcbuf, t8c) 112 if emode==1 { vv_dec_rct8(prevD, reconD, W, H, qp, outT, tb, blk, mv, rctx) } 113 else { vv_dec_t8(prevD, reconD, W, H, qp, outT, tb, blk, mv, rctx) } 114 let ok: i64 = eqb(reconD, reconT, sz) 115 if ok==1 { p[0]=p[0]+1 } 116 gw(" f" as *u8); gn(f); if key==1 { gw(" KEY " as *u8) } else { gw(" P " as *u8) } 117 gw("base=" as *u8); gn(cb); gw("B t8=" as *u8); gn(tb); gw("B (" as *u8); gn(tb*100/cb); gw("%) " as *u8) 118 if ok==1 { gw("BIT-EXACT\n" as *u8) } else { gw("MISMATCH\n" as *u8) } 119 } else { gw(" f" as *u8); gn(f); gw(" ENC FAILED\n" as *u8) } 120 sums[0]=sums[0]+tb; sums[1]=sums[1]+cb 121 cpb(prevC, reconC, sz); cpb(prevT, reconT, sz); cpb(prevD, reconD, sz) 122 f=f+1 123 } 124 return 0 } 125 126// single keyframe RD: bytes + luma PSNR, t8 vs 4x4 baseline, at emode. kind 0=flat 1=textured. 127// pr[0]=base bytes, pr[1]=t8 bytes, pr[2]=base dB, pr[3]=t8 dB 128func run_key(W: i64, H: i64, qp: i64, emode: i64, kind: i64, pr: *i64) -> i64 { 129 let N: i64=W*H; let C2: i64=(W/2)*(H/2); let sz: i64=N+2*C2 130 let cur: *u8=sys_mmap(sz); let prev: *u8=sys_mmap(sz) 131 let reconC: *u8=sys_mmap(sz); let reconT: *u8=sys_mmap(sz) 132 let blk: *i64=sys_mmap(512) as *i64; let mv: *i64=sys_mmap(128) as *i64 133 let outC: *u8=sys_mmap(262144); let outT: *u8=sys_mmap(262144) 134 let est: *i64=sys_mmap(64) as *i64; let probs: *i64=sys_mmap(32*8) as *i64; let rcbuf: *u8=sys_mmap(262144) 135 let rctx: *i64=sys_mmap(8*8) as *i64 136 let t8c: *i64=sys_mmap(5120) as *i64 137 vc_t8_init(t8c) 138 if kind==0 { fill_flat(cur, W, H) } else { fill_tex(cur, W, H) } 139 var cb: i64=0 140 if emode==1 { seedctx(rctx, 1, est, probs, rcbuf, t8c) 141 cb = vv_enc_rc(cur, prev, reconC, W, H, qp, 1, 6016, outC, 262144, blk, mv, rctx) } 142 else { cb = vv_enc(cur, prev, reconC, W, H, qp, 1, 6016, outC, 262144, blk, mv) } 143 seedctx(rctx, emode, est, probs, rcbuf, t8c) 144 var tb: i64=0 145 if emode==1 { tb = vv_enc_rct8(cur, prev, reconT, W, H, qp, 1, 6016, outT, 262144, blk, mv, rctx) } 146 else { tb = vv_enc_t8(cur, prev, reconT, W, H, qp, 1, 6016, outT, 262144, blk, mv, rctx) } 147 let sC: i64 = sseL(reconC, cur, N) 148 let sT: i64 = sseL(reconT, cur, N) 149 pr[0]=cb; pr[1]=tb 150 let dC: i64 = psnrdb(sC, N) 151 let dT: i64 = psnrdb(sT, N) 152 pr[2]=dC; pr[3]=dT 153 return 0 } 154 155func main() -> i64 { 156 gw("=== nx_vcodec_t8_gate: per-MB variable transform (8x8 flat / 4x4 textured, 1 bit/MB) ===\n" as *u8) 157 let p: *i64=sys_mmap(16) as *i64; let t: *i64=sys_mmap(16) as *i64 158 let sums: *i64=sys_mmap(32) as *i64 159 let pr: *i64=sys_mmap(64) as *i64 160 gw(" [1] CAVLC t8 chain 256x192 (key + 4 P, mixed moving content):\n" as *u8) 161 run_chain(256, 192, 20, 0, p, t, sums) 162 gw(" chain total: t8=" as *u8); gn(sums[0]); gw("B vs base=" as *u8); gn(sums[1]); gw("B\n" as *u8) 163 gw(" [2] RANGE t8 chain 256x192:\n" as *u8) 164 run_chain(256, 192, 20, 1, p, t, sums) 165 gw(" chain total: rct8=" as *u8); gn(sums[0]); gw("B vs rc=" as *u8); gn(sums[1]); gw("B\n" as *u8) 166 // [3] flat keyframe RD, CAVLC: t8 must be strictly smaller at PSNR within 1 dB 167 run_key(256, 192, 20, 0, 0, pr) 168 gw(" [3] FLAT key CAVLC: 4x4=" as *u8); gn(pr[0]); gw("B@" as *u8); gn(pr[2]); gw("dB t8=" as *u8) 169 gn(pr[1]); gw("B@" as *u8); gn(pr[3]); gw("dB (" as *u8); gn(pr[1]*100/pr[0]); gw("%)\n" as *u8) 170 t[0]=t[0]+1; if pr[1] < pr[0] { if pr[3] >= pr[2]-1 { p[0]=p[0]+1 } } 171 // [4] flat keyframe RD, RANGE: rct8 must be strictly smaller than rc 172 run_key(256, 192, 20, 1, 0, pr) 173 gw(" [4] FLAT key RANGE: rc=" as *u8); gn(pr[0]); gw("B@" as *u8); gn(pr[2]); gw("dB rct8=" as *u8) 174 gn(pr[1]); gw("B@" as *u8); gn(pr[3]); gw("dB (" as *u8); gn(pr[1]*100/pr[0]); gw("%)\n" as *u8) 175 t[0]=t[0]+1; if pr[1] < pr[0] { if pr[3] >= pr[2]-1 { p[0]=p[0]+1 } } 176 // [5] textured keyframe (policy keeps 4x4 -> expect ~parity; only the 1 bit/MB overhead) -- report 177 run_key(256, 192, 20, 0, 1, pr) 178 gw(" [5] TEX key CAVLC (info): 4x4=" as *u8); gn(pr[0]); gw("B@" as *u8); gn(pr[2]); gw("dB t8=" as *u8) 179 gn(pr[1]); gw("B@" as *u8); gn(pr[3]); gw("dB (" as *u8); gn(pr[1]*100/pr[0]); gw("%)\n" as *u8) 180 gw("T8: " as *u8); gn(p[0]); gw("/" as *u8); gn(t[0]) 181 if p[0]==t[0] { gw(" verdict=GREEN -- variable transform decodes bit-exact + wins bytes on flat at matched quality\n" as *u8); return 0 } 182 gw(" verdict=RED\n" as *u8); return 1 }