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 }