code wiki / _hdl_build / nx_vcodec_mrbits_gate.nx
nx_vcodec_mrbits_gate.nx source
↩ module page · 122 lines · 7267 B
1// nx_vcodec_mrbits_gate.nx -- the REALIZED-BITS test of multi-reference prediction (does the vcv-7 build pay
2// for itself?). The earlier nx_vcodec_multiref_gate measured residual SAD (an upper bound); this measures the
3// ACTUAL CODED BITS: per 16x16 inter MB, ME on each reference -> real DCT+RDOQ residual entropy cost (ve_cost,
4// the range coder's monotone proxy) + MV cost. Single-ref always uses N-1; multi-ref picks the cheaper of
5// {N-1, N-2} and PAYS the 1-bit/MB ref-index. If multi-ref total bits < single-ref AFTER the overhead, the
6// gain is REAL and the vcv-7 build is justified; if not, multi-ref loses to its own signaling and we DON'T
7// build it (measure-first, no half-build). GREEN = reports the realized delta + it's positive. ORIGINAL.
8import "nx_syscalls.nx"
9import "nx_vmotion.nx"
10import "nx_vtransform_dct2.nx"
11import "nx_ventropy.nx"
12import "nx_vcodec.nx" // vt2_quant_rdoq (shipped quant)
13
14const NW: i64 = 576
15const NH: i64 = 1024
16const T: i64 = 16
17const RSEARCH: i64 = 8
18
19func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
20func gn(v: i64) -> i64 {
21 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
22 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}
23 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
24
25func mvbits(v: i64) -> i64 { return 5 + ve_blen(ve_zze(v)) } // ve_vput MV component cost
26
27// total coded bits for a 16x16 inter MB predicted from `ref` at integer MV (mvx,mvy): residual entropy
28// (16 x 4x4 DCT+RDOQ + ve_cost) + MV cost. blk = i64[16] scratch. edge-guarded by the caller.
29func mb_bits(cur: *u8, ref: *u8, W: i64, cx: i64, cy: i64, mvx: i64, mvy: i64, qp: i64, blk: *i64) -> i64 {
30 var bits: i64 = mvbits(mvx) + mvbits(mvy)
31 var sj: i64=0
32 while sj < 4 { var si: i64=0
33 while si < 4 {
34 let sx: i64=cx+si*4; let sy: i64=cy+sj*4
35 var yy: i64=0
36 while yy<4 { var xx: i64=0
37 while xx<4 { let c: i64=cur[(sy+yy)*W+sx+xx]&0xff; let p: i64=ref[(sy+yy+mvy)*W+sx+xx+mvx]&0xff; blk[yy*4+xx]=c-p; xx=xx+1 } yy=yy+1 }
38 vt2_fwd(blk); vt2_quant_rdoq(blk, qp)
39 bits = bits + ve_cost(blk)
40 si=si+1 } sj=sj+1 }
41 return bits }
42
43// COMPOUND: residual = cur - avg(r1@mv1, r2@mv2). Both MVs coded (heavier overhead than single).
44func mb_bits_compound(cur: *u8, r1: *u8, r2: *u8, W: i64, cx: i64, cy: i64, mvx1: i64, mvy1: i64, mvx2: i64, mvy2: i64, qp: i64, blk: *i64) -> i64 {
45 var bits: i64 = mvbits(mvx1) + mvbits(mvy1) + mvbits(mvx2) + mvbits(mvy2)
46 var sj: i64=0
47 while sj < 4 { var si: i64=0
48 while si < 4 {
49 let sx: i64=cx+si*4; let sy: i64=cy+sj*4
50 var yy: i64=0
51 while yy<4 { var xx: i64=0
52 while xx<4 {
53 let c: i64=cur[(sy+yy)*W+sx+xx]&0xff
54 let p1: i64=r1[(sy+yy+mvy1)*W+sx+xx+mvx1]&0xff
55 let p2: i64=r2[(sy+yy+mvy2)*W+sx+xx+mvx2]&0xff
56 blk[yy*4+xx]=c-((p1+p2+1)/2); xx=xx+1 } yy=yy+1 }
57 vt2_fwd(blk); vt2_quant_rdoq(blk, qp)
58 bits = bits + ve_cost(blk)
59 si=si+1 } sj=sj+1 }
60 return bits }
61
62func main() -> i64 {
63 let vmscr3: *i64 = sys_mmap(32) as *i64 // vm_search scratch (2026-07-29: hoisted ONE alloc; the per-call sys_mmap inside vm_search was the wasm 0-stub + native map-leak class)
64 gw("=== nx_vcodec_mrbits_gate: REALIZED bits, single-ref(N-1) vs multi-ref(N-1|N-2) + 1bit/MB overhead ===\n" as *u8)
65 let box: *i64=sys_mmap(16) as *i64
66 let yuv: *u8=sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/knowledge/staging/media/bframe_test_decoded.yuv" as *u8, box)
67 if (yuv as i64)==0 { gw("cannot read yuv -> verdict=RED\n" as *u8); return 1 }
68 let N: i64=NW*NH; let FB: i64=N+N/2
69 if box[0] < 12*FB { gw("file too small -> verdict=RED\n" as *u8); return 1 }
70 let mv1: *i64=sys_mmap(32) as *i64; let mv2: *i64=sys_mmap(32) as *i64
71 let blk: *i64=sys_mmap(64) as *i64
72 let qp: i64=28
73
74 var bSingle: i64=0; var bMulti: i64=0; var bComp: i64=0; var nInter: i64=0; var picked2: i64=0; var pickedC: i64=0
75 var f: i64=8
76 while f<12 {
77 let cur: *u8=((yuv as i64)+f*FB) as *u8
78 let r1: *u8=((yuv as i64)+(f-1)*FB) as *u8
79 let r2: *u8=((yuv as i64)+(f-2)*FB) as *u8
80 var by: i64=0
81 while by<NH/T { var bx: i64=0
82 while bx<NW/T {
83 let cx: i64=bx*T; let cy: i64=by*T
84 vm_search(cur, r1, NW, NH, bx, by, T, RSEARCH, mv1, vmscr3)
85 vm_search(cur, r2, NW, NH, bx, by, T, RSEARCH, mv2, vmscr3)
86 var ok1: i64=1; if cx+mv1[0]<0 {ok1=0} if cy+mv1[1]<0 {ok1=0} if cx+mv1[0]+T>NW {ok1=0} if cy+mv1[1]+T>NH {ok1=0}
87 var ok2: i64=1; if cx+mv2[0]<0 {ok2=0} if cy+mv2[1]<0 {ok2=0} if cx+mv2[0]+T>NW {ok2=0} if cy+mv2[1]+T>NH {ok2=0}
88 if ok1==1 {
89 let b1: i64 = mb_bits(cur, r1, NW, cx, cy, mv1[0], mv1[1], qp, blk)
90 bSingle = bSingle + b1
91 // multi-ref: best of {N-1, N-2} + 1 ref bit
92 var bm: i64 = b1
93 if ok2==1 { let b2: i64 = mb_bits(cur, r2, NW, cx, cy, mv2[0], mv2[1], qp, blk); if b2 < bm { bm=b2; picked2=picked2+1 } }
94 bMulti = bMulti + bm + 1
95 // compound: min(single N-1 + 1 flag, compound + 1 flag). compound codes a 2nd MV.
96 var bc: i64 = b1 + 1 // single mode (flag=0)
97 if ok2==1 {
98 let bcmp: i64 = mb_bits_compound(cur, r1, r2, NW, cx, cy, mv1[0], mv1[1], mv2[0], mv2[1], qp, blk) + 1 // flag=1 + 2nd MV inside
99 if bcmp < bc { bc=bcmp; pickedC=pickedC+1 }
100 }
101 bComp = bComp + bc
102 nInter = nInter + 1
103 }
104 bx=bx+1 } by=by+1 }
105 f=f+1
106 }
107 gw(" inter MBs=" as *u8); gn(nInter); gw(" chose N-2=" as *u8); gn(picked2); gw(" chose compound=" as *u8); gn(pickedC); gw("\n" as *u8)
108 gw(" single-ref=" as *u8); gn(bSingle); gw(" multi-ref=" as *u8); gn(bMulti); gw(" compound=" as *u8); gn(bComp); gw("\n" as *u8)
109 var svM: i64=0; if bSingle>0 { svM=(bSingle-bMulti)*1000/bSingle }
110 var svC: i64=0; if bSingle>0 { svC=(bSingle-bComp)*1000/bSingle }
111 gw(" REALIZED saving: multi-ref=" as *u8); gn(svM); gw("permille compound=" as *u8); gn(svC); gw("permille (after overhead)\n" as *u8)
112
113 var pass: i64=0; var tot: i64=0
114 tot=tot+1; if nInter > 1000 { pass=pass+1 }
115 tot=tot+1; if bMulti <= bSingle { pass=pass+1 }
116 tot=tot+1; if bComp <= bSingle { pass=pass+1 }
117 gw("MRBITS: " as *u8); gn(pass); gw("/" as *u8); gn(tot)
118 var best: i64=svM; if svC>best { best=svC }
119 if pass==tot {
120 if best >= 20 { gw(" verdict=GREEN -- a prediction rung saves >=2pct REALIZED: JUSTIFIED (build the winner)\n" as *u8); return 0 }
121 gw(" verdict=GREEN -- prediction rungs all <2pct realized: MARGINAL for this content, NOT worth the wire (measure-first payoff)\n" as *u8); return 0 }
122 gw(" verdict=RED\n" as *u8); return 1 }