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 }