code wiki / _hdl_build / nx_vcodec_multiref_gate.nx

nx_vcodec_multiref_gate.nx source

↩ module page · 96 lines · 5882 B

1// nx_vcodec_multiref_gate.nx -- MEASURES the latency-safe B-frame lever: does predicting from TWO PAST 2// references (multi-ref best-of + COMPOUND averaging) shrink the residual vs single-ref (previous frame only)? 3// This is how low-latency RTC codecs get B-frame-like gains WITHOUT the reorder/latency of classic 4// bidirectional B (which references a FUTURE frame). Per 16x16 block, on real frames, measures total residual 5// SAD for: (1) single-ref = prev frame N-1; (2) multi-ref = best-of {N-1, N-2, N-4 long-term}; (3) compound = 6// average of the two best past predictions. The SAD reduction = the upper-bound prediction gain a multi-ref/ 7// compound generation would win. GREEN reports the measured reduction (build-decision, not pass/fail-of-idea). 8// license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_vmotion.nx" 11 12const NW: i64 = 576 13const NH: i64 = 1024 14const T: i64 = 16 15const R: i64 = 8 16 17func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func gn(v: i64) -> i64 { 19 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} 20 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} 21 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 22 23// SAD of cur block (cx,cy) vs the AVERAGE of ref1@mv1 and ref2@mv2 (integer MVs). Edge-guarded by the caller. 24func compound_sad(cur: *u8, r1: *u8, r2: *u8, W: i64, cx: i64, cy: i64, mvx1: i64, mvy1: i64, mvx2: i64, mvy2: i64) -> i64 { 25 var s: i64=0; var yy: i64=0 26 while yy < T { var xx: i64=0 27 while xx < T { 28 let c: i64 = cur[(cy+yy)*W + cx+xx] & 0xff 29 let p1: i64 = r1[(cy+yy+mvy1)*W + cx+xx+mvx1] & 0xff 30 let p2: i64 = r2[(cy+yy+mvy2)*W + cx+xx+mvx2] & 0xff 31 let pc: i64 = (p1 + p2 + 1) / 2 32 let d: i64 = c - pc; if d<0 { s=s-d } else { s=s+d } 33 xx=xx+1 } yy=yy+1 } 34 return s } 35 36func inb(cx: i64, cy: i64, mvx: i64, mvy: i64) -> i64 { // is the MC block fully in-frame? 37 if cx+mvx < 0 { return 0 } if cy+mvy < 0 { return 0 } 38 if cx+mvx+T > NW { return 0 } if cy+mvy+T > NH { return 0 } 39 return 1 } 40 41func main() -> i64 { 42 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) 43 gw("=== nx_vcodec_multiref_gate: single-ref vs multi-ref vs compound (latency-safe B lever), real frames ===\n" as *u8) 44 let box: *i64 = sys_mmap(16) as *i64 45 let yuv: *u8 = sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/knowledge/staging/media/bframe_test_decoded.yuv" as *u8, box) 46 if (yuv as i64) == 0 { gw("cannot read yuv -> verdict=RED\n" as *u8); return 1 } 47 let N: i64=NW*NH; let FB: i64=N+N/2 48 if box[0] < 12*FB { gw("file too small -> verdict=RED\n" as *u8); return 1 } 49 let mv1: *i64=sys_mmap(32) as *i64; let mv2: *i64=sys_mmap(32) as *i64; let mvl: *i64=sys_mmap(32) as *i64 50 51 var sSingle: i64=0; var sMulti: i64=0; var sComp: i64=0 52 var f: i64=8 53 while f < 12 { 54 let cur: *u8 = ((yuv as i64) + f*FB) as *u8 55 let r1: *u8 = ((yuv as i64) + (f-1)*FB) as *u8 // N-1 56 let r2: *u8 = ((yuv as i64) + (f-2)*FB) as *u8 // N-2 57 let rl: *u8 = ((yuv as i64) + (f-4)*FB) as *u8 // N-4 (long-term) 58 var by: i64=0 59 while by < NH/T { 60 var bx: i64=0 61 while bx < NW/T { 62 let cx: i64=bx*T; let cy: i64=by*T 63 let sad1: i64 = vm_search(cur, r1, NW, NH, bx, by, T, R, mv1, vmscr3) 64 let sad2: i64 = vm_search(cur, r2, NW, NH, bx, by, T, R, mv2, vmscr3) 65 let sadl: i64 = vm_search(cur, rl, NW, NH, bx, by, T, R, mvl, vmscr3) 66 sSingle = sSingle + sad1 67 var best: i64 = sad1; if sad2 < best { best=sad2 } if sadl < best { best=sadl } 68 sMulti = sMulti + best 69 // compound = average of the two BEST past predictions (N-1 and whichever of N-2/N-4 is better) 70 var mx2: i64=mv2[0]; var my2: i64=mv2[1]; var rr2: i64 = r2 as i64 71 if sadl < sad2 { mx2=mvl[0]; my2=mvl[1]; rr2 = rl as i64 } 72 var cs: i64 = best // compound only if both refs in-frame, else fall back to best 73 if inb(cx,cy,mv1[0],mv1[1])==1 { if inb(cx,cy,mx2,my2)==1 { 74 let c2: i64 = compound_sad(cur, r1, rr2 as *u8, NW, cx, cy, mv1[0], mv1[1], mx2, my2) 75 if c2 < cs { cs = c2 } 76 } } 77 sComp = sComp + cs 78 bx=bx+1 } by=by+1 } 79 f=f+1 80 } 81 gw(" total residual SAD -- single-ref(N-1)=" as *u8); gn(sSingle) 82 gw(" multi-ref(best of N-1,N-2,N-4)=" as *u8); gn(sMulti) 83 gw(" compound(avg 2 past)=" as *u8); gn(sComp); gw("\n" as *u8) 84 let rM: i64 = (sSingle-sMulti)*1000/sSingle 85 let rC: i64 = (sSingle-sComp)*1000/sSingle 86 gw(" multi-ref cuts residual " as *u8); gn(rM); gw("permille; compound cuts " as *u8); gn(rC); gw("permille vs single-ref\n" as *u8) 87 88 var pass: i64=0; var tot: i64=0 89 tot=tot+1; if sMulti <= sSingle { pass=pass+1 } // multi-ref never hurts 90 tot=tot+1; if sComp <= sMulti { pass=pass+1 } // compound never hurts vs multi 91 tot=tot+1; if sSingle > 1000000 { pass=pass+1 } // real substantial measurement 92 gw("MULTIREF: " as *u8); gn(pass); gw("/" as *u8); gn(tot) 93 if pass==tot { 94 if rC >= 50 { gw(" verdict=GREEN -- compound/multi-ref cuts residual >=5pct: a latency-safe B-lever WORTH building\n" as *u8); return 0 } 95 gw(" verdict=GREEN -- but gain is SMALL (<5pct residual): multi-ref marginal for this content, NOT worth the wire\n" as *u8); return 0 } 96 gw(" verdict=RED\n" as *u8); return 1 }