code wiki / _hdl_build / nx_vcodec_sigcoder_gate.nx
nx_vcodec_sigcoder_gate.nx source
↩ module page · 206 lines · 9796 B
1import "nx_gate_base.nx"
2// nx_vcodec_sigcoder_gate.nx -- R2a PROOF, honest 2x2: {run-length rc_block64 | significance-map rc_sig}
3// x {uniform-2048 priors | TRAINED priors}. The live codec seeds every context to 2048 PER FRAME (see
4// vc_enc_frame_packed_rc) and pays the adaptation ramp every frame; TRAINED priors (empirical bit counts on
5// TRAIN frames, applied to HELD-OUT frames) are the first genuinely LEARNED entropy component -- the same
6// move as VP8/VP9's offline-trained default probability tables and the learned CDF tables of neural codecs.
7// Per-frame streams mirror the live behavior exactly. GREEN = sig-map bit-exact roundtrip on held-out data,
8// trained priors never hurt, and the best config beats the live config (RL+uniform) by a reported permille.
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_dct8.nx"
12import "nx_vcodec.nx"
13import "nx_rangecoder.nx"
14import "nx_rangecoder_sig.nx"
15
16const NW: i64 = 576
17const NH: i64 = 1024
18const BPF: i64 = 9216 // 8x8 luma blocks per frame = (576/8)*(1024/8)
19
20func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
21" as *u8); return ok }
22func gn(v: i64) -> i64 {
23 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
24 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}
25 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
26
27// fill BPF quantized 8x8 coefficient blocks for the diff of frame f vs f-1 into dst
28func fill_frame(yuv: *u8, f: i64, qp: i64, M: *i64, scr: *i64, ti: *i64, to: *i64, dst: *i64) -> i64 {
29 let N: i64=NW*NH; let FB: i64=N+N/2
30 let cur: *u8 = ((yuv as i64) + f*FB) as *u8
31 let prv: *u8 = ((yuv as i64) + (f-1)*FB) as *u8
32 var nb: i64 = 0
33 var by: i64 = 0
34 while by < NH/8 { var bx: i64 = 0
35 while bx < NW/8 {
36 let blk: *i64 = ((dst as i64) + nb*64*8) as *i64
37 var yy: i64=0
38 while yy < 8 { var xx: i64=0
39 while xx < 8 { let p: i64=(by*8+yy)*NW+(bx*8+xx); blk[yy*8+xx]=(cur[p]&0xff)-(prv[p]&0xff); xx=xx+1 } yy=yy+1 }
40 nx_dct8_forward_2d(M, blk, blk, scr, ti, to)
41 vc_quant8(blk, qp)
42 nb = nb + 1
43 bx=bx+1 } by=by+1 }
44 return nb }
45
46// ---- TRAINING TALLIES: mirror each coder's bit decisions, counting (ctx, bit) into h[ctx*2+bit] ----
47func tally_rl(blocks: *i64, nb: i64, zz8: *i64, h: *i64) -> i64 {
48 var b: i64=0
49 while b < nb {
50 let c: *i64 = ((blocks as i64)+b*64*8) as *i64
51 var run: i64=0; var k: i64=0
52 while k < 64 {
53 let val: i64 = c[zz8[k]]
54 if val == 0 { run = run + 1 } else {
55 h[11*2+1] = h[11*2+1] + 1
56 var bi: i64=5; while bi >= 0 { let bit: i64=(run>>bi)&1; h[(12+(5-bi))*2+bit]=h[(12+(5-bi))*2+bit]+1; bi=bi-1 }
57 let z: i64 = ve_zze(val); let nbl: i64 = ve_blen(z)
58 bi = 4; while bi >= 0 { let bit2: i64=(nbl>>bi)&1; h[(18+(4-bi))*2+bit2]=h[(18+(4-bi))*2+bit2]+1; bi=bi-1 }
59 var m: i64 = nbl - 1; while m >= 0 { let bit3: i64=(z>>m)&1; h[23*2+bit3]=h[23*2+bit3]+1; m=m-1 }
60 run = 0
61 }
62 k = k + 1
63 }
64 h[11*2] = h[11*2] + 1 // EOB
65 b=b+1
66 }
67 return 0 }
68func tally_sig(blocks: *i64, nb: i64, sigmap: *i64, h: *i64) -> i64 {
69 var b: i64=0
70 while b < nb {
71 let c: *i64 = ((blocks as i64)+b*64*8) as *i64
72 var anynz: i64=0; var i: i64=0
73 while i < 64 { if c[i] != 0 { anynz=1 } sigmap[i]=0; i=i+1 }
74 h[0*2+anynz] = h[0*2+anynz] + 1
75 if anynz == 1 {
76 var p: i64=0
77 while p < 64 {
78 let nbr: i64 = rcs_nb(sigmap, p, 8)
79 var s: i64=0; if c[p] != 0 { s=1 }
80 let cx: i64 = rcs_sigctx(p, 64, nbr)
81 h[cx*2+s] = h[cx*2+s] + 1
82 sigmap[p] = s
83 p=p+1
84 }
85 p=0
86 while p < 64 { if c[p] != 0 {
87 var mag: i64=c[p]; var sgn: i64=0; if mag<0 { mag=0-mag; sgn=1 }
88 let nbl: i64 = ve_blen(mag)
89 var bi: i64=4; while bi >= 0 { let bit: i64=(nbl>>bi)&1; h[(17+(4-bi))*2+bit]=h[(17+(4-bi))*2+bit]+1; bi=bi-1 }
90 var m: i64 = nbl-2; while m >= 0 { let bit2: i64=(mag>>m)&1; h[22*2+bit2]=h[22*2+bit2]+1; m=m-1 }
91 h[23*2+sgn] = h[23*2+sgn] + 1
92 } p=p+1 }
93 }
94 b=b+1
95 }
96 return 0 }
97// counts -> 12-bit P(bit==0), clamped so adaptation can still move
98func mk_priors(h: *i64, nctx: i64, pr: *i64) -> i64 {
99 var c: i64=0
100 while c < nctx {
101 let n0: i64=h[c*2]; let n1: i64=h[c*2+1]; let tot: i64=n0+n1
102 var p: i64 = 2048
103 if tot > 0 { p = (n0*4096)/tot }
104 if p < 64 { p = 64 }
105 if p > 4032 { p = 4032 }
106 pr[c] = p
107 c=c+1
108 }
109 return 0 }
110
111// encode one frame's blocks with the chosen coder + priors; returns bytes. mode 0=RL, 1=SIG.
112func enc_frame(blocks: *i64, nb: i64, mode: i64, priors: *i64, nctx: i64, zz8: *i64, sigmap: *i64,
113 est: *i64, probs: *i64, out: *u8) -> i64 {
114 rc_enc_init(est)
115 var ci: i64=0; while ci < nctx { probs[ci]=priors[ci]; ci=ci+1 }
116 var b: i64=0
117 while b < nb {
118 let c: *i64 = ((blocks as i64)+b*64*8) as *i64
119 if mode == 0 { rc_block64_encode(c, est, out, probs, zz8) }
120 else { rc_sig_encode(c, 64, 8, est, out, probs, sigmap) }
121 b=b+1
122 }
123 return rc_enc_flush(est, out) }
124
125func main() -> i64 {
126 gw("=== nx_vcodec_sigcoder_gate v2: {RL|SIG} x {uniform|TRAINED priors}, per-frame, held-out ===\n" as *u8)
127 let box: *i64 = sys_mmap(16) as *i64
128 let yuv: *u8 = sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/knowledge/staging/media/bframe_test_decoded.yuv" as *u8, box)
129 if (yuv as i64) == 0 { gw("cannot read yuv -> RED\n" as *u8); return 1 }
130 if box[0] < 12*(NW*NH+NW*NH/2) { gw("file too small -> RED\n" as *u8); return 1 }
131 let M: *i64 = sys_mmap(64*8) as *i64; nx_dct8_init(M)
132 let scr: *i64 = sys_mmap(64*8) as *i64; let ti: *i64 = sys_mmap(8*8) as *i64; let to: *i64 = sys_mmap(8*8) as *i64
133 let t8c: *i64 = sys_mmap(5120) as *i64; vc_t8_init(t8c)
134 let zz8: *i64 = vc_t8p(t8c, VC_T8_ZZ)
135 let sigmap: *i64 = sys_mmap(64*8) as *i64
136 let fblocks: *i64 = sys_mmap(BPF*64*8) as *i64
137 let qp: i64 = 28
138
139 // ---- TRAIN on frames 8,9 (diffs 8-7, 9-8) ----
140 let hRL: *i64 = sys_mmap(32*2*8) as *i64
141 let hSG: *i64 = sys_mmap(32*2*8) as *i64
142 var z: i64=0; while z<64 { hRL[z]=0; hSG[z]=0; z=z+1 }
143 var f: i64=8
144 while f < 10 {
145 let nb: i64 = fill_frame(yuv, f, qp, M, scr, ti, to, fblocks)
146 tally_rl(fblocks, nb, zz8, hRL)
147 tally_sig(fblocks, nb, sigmap, hSG)
148 f=f+1
149 }
150 let prRL: *i64 = sys_mmap(32*8) as *i64
151 let prSG: *i64 = sys_mmap(32*8) as *i64
152 mk_priors(hRL, RC_NCTX8, prRL)
153 mk_priors(hSG, RC_SIG_NCTX, prSG)
154 let un: *i64 = sys_mmap(32*8) as *i64
155 z=0; while z<32 { un[z]=2048; z=z+1 }
156
157 // ---- EVAL on HELD-OUT frames 10,11 (per-frame streams, like the live codec) ----
158 let est: *i64 = sys_mmap(64) as *i64
159 let probs: *i64 = sys_mmap(32*8) as *i64
160 let out: *u8 = sys_mmap(8388608)
161 var bRLu: i64=0; var bRLt: i64=0; var bSGu: i64=0; var bSGt: i64=0
162 var mism: i64=0
163 let dblk: *i64 = sys_mmap(64*8) as *i64
164 let dprobs: *i64 = sys_mmap(32*8) as *i64
165 let dst: *i64 = sys_mmap(64) as *i64
166 f=10
167 while f < 12 {
168 let nb: i64 = fill_frame(yuv, f, qp, M, scr, ti, to, fblocks)
169 bRLu = bRLu + enc_frame(fblocks, nb, 0, un, RC_NCTX8, zz8, sigmap, est, probs, out)
170 bRLt = bRLt + enc_frame(fblocks, nb, 0, prRL, RC_NCTX8, zz8, sigmap, est, probs, out)
171 bSGu = bSGu + enc_frame(fblocks, nb, 1, un, RC_SIG_NCTX, zz8, sigmap, est, probs, out)
172 // SIG+trained: keep the stream in `out` and VERIFY the bit-exact roundtrip block-by-block
173 let nB: i64 = enc_frame(fblocks, nb, 1, prSG, RC_SIG_NCTX, zz8, sigmap, est, probs, out)
174 bSGt = bSGt + nB
175 rc_dec_init(dst, out)
176 var ci: i64=0; while ci < RC_SIG_NCTX { dprobs[ci]=prSG[ci]; ci=ci+1 }
177 var b: i64=0
178 while b < nb {
179 rc_sig_decode(dblk, 64, 8, dst, out, dprobs, sigmap)
180 let src: *i64 = ((fblocks as i64)+b*64*8) as *i64
181 var i: i64=0; while i < 64 { if dblk[i] != src[i] { mism=mism+1; i=64 } i=i+1 }
182 b=b+1
183 }
184 f=f+1
185 }
186
187 gw(" held-out bytes: RL+uniform(LIVE)=" as *u8); gn(bRLu)
188 gw(" RL+trained=" as *u8); gn(bRLt)
189 gw(" SIG+uniform=" as *u8); gn(bSGu)
190 gw(" SIG+trained=" as *u8); gn(bSGt)
191 gw(" mism=" as *u8); gn(mism); gw("\n" as *u8)
192 let svSGt: i64 = (bRLu - bSGt)*1000/bRLu
193 let svTR: i64 = (bRLu - bRLt)*1000/bRLu
194 let svSG: i64 = (bRLu - bSGu)*1000/bRLu
195 gw(" vs LIVE: sig-map alone " as *u8); gn(svSG)
196 gw("permille · trained-priors alone " as *u8); gn(svTR)
197 gw("permille · BOTH " as *u8); gn(svSGt); gw("permille\n" as *u8)
198
199 var pass: i64=0; var tot: i64=0
200 tot=tot+1; if mism == 0 { pass=pass+1 } // held-out bit-exact roundtrip
201 tot=tot+1; if bRLt <= bRLu { pass=pass+1 } // trained priors never hurt (RL)
202 tot=tot+1; if bSGt <= bSGu { pass=pass+1 } // trained priors never hurt (SIG)
203 tot=tot+1; if bSGt < bRLu { pass=pass+1 } // best config beats LIVE
204 gw("SIGCODER2: " as *u8); gn(pass); gw("/" as *u8); gn(tot)
205 if pass==tot { gw(" GREEN -- learned priors + neighbor-context sig-map beat the live coder on held-out frames\n" as *u8); return 0 }
206 gw(" RED\n" as *u8); return 1 }