code wiki / _hdl_build / nx_vcodec_mvbits_probe.nx

nx_vcodec_mvbits_probe.nx source

↩ module page · 124 lines · 7883 B

1// nx_vcodec_mvbits_probe.nx -- MEASURE the MV-coding overhead (handoff doctrine: sensor before build). Our MV 2// syntax is ve_vput = flat [5-bit length][payload] per component + 4 qpel bits, coded ABSOLUTE (no prediction). 3// x264 codes MV DELTAS vs the median of {left, top, top-right} neighbours -- near-zero deltas on smooth motion 4// fields. This probe runs the REAL encoder (emode 4005, recon-chained, key+11P like arm_p) and, per coded MB, 5// re-derives the same skip gate + integer/qpel-free MV the coder finds, tallying: (a) actual ve_vput bits, 6// (b) bits if coded as delta-vs-median with the SAME VLC, (c) delta-vs-median with an exp-golomb VLC (the 7// H.264-class mvd code). Against the frame's REAL total bytes -> MV share % and the measured prize of median 8// prediction. Approximation: 16x16-level only (partition sub-MVs ignored -> UNDER-counts, conservative). license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_video_codec_wasm.nx" 11import "nx_quality_metric.nx" 12 13const NW: i64 = 576 14const NH: i64 = 1024 15const EMODE: i64 = 4005 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 23func seedctxe(rctx: *i64, emode: i64, est: *i64, probs: *i64, rcbuf: *u8, t8c: *i64) -> i64 { 24 rctx[0]=emode; rctx[1]=est as i64; rctx[2]=probs as i64; rctx[3]=rcbuf as i64; rctx[4]=t8c as i64 25 rctx[5]=0; rctx[6]=0; rctx[7]=0; rctx[8]=0; rctx[9]=sys_mmap(4096) as i64; return 0 } // rctx[9] = vcv-10 MV row-plane ([6]/[7]=nf, [8]=heat are TAKEN); 4KB covers W<=2048 26func zero(p: *u8, n: i64) -> i64 { var i: i64=0; while i<n { p[i]=0 as u8; i=i+1 } return 0 } 27func zze(v: i64) -> i64 { if v < 0 { return ((0 - v) << 1) - 1 } return v << 1 } 28func blen(z: i64) -> i64 { var n: i64 = 0; var x: i64 = z; while x > 0 { n = n + 1; x = x >> 1 } return n } 29// our VLC cost for a signed value (ve_vput): 5-bit length + payload 30func vbits(v: i64) -> i64 { return 5 + blen(zze(v)) } 31// exp-golomb ue(zze(v)) cost: 2*blen(z+1)-1 (the H.264 mvd-class code) 32func gbits(v: i64) -> i64 { return 2*blen(zze(v)+1) - 1 } 33func med3(a: i64, b: i64, c: i64) -> i64 { 34 var lo: i64 = a; if b < lo { lo = b } if c < lo { lo = c } 35 var hi: i64 = a; if b > hi { hi = b } if c > hi { hi = c } 36 return a + b + c - lo - hi } 37 38func main() -> i64 { 39 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) 40 gw("=== nx_vcodec_mvbits_probe: MV-coding overhead + median-prediction prize (emode 4005, real chain) ===\n" as *u8) 41 let box: *i64 = sys_mmap(16) as *i64 42 let yuv: *u8 = sys_read_file("/mnt/c/Users/elder/nishi-core/nxc2/knowledge/staging/media/bframe_test_decoded.yuv" as *u8, box) 43 if (yuv as i64) == 0 { gw("cannot read yuv -> RED\n" as *u8); return 1 } 44 let N: i64=NW*NH; let C2: i64=(NW/2)*(NH/2); let sz: i64=N+2*C2 45 let FB: i64 = N + N/2 46 if box[0] < 12 * FB { gw("file too small -> RED\n" as *u8); return 1 } 47 let e0: *u8 = sys_mmap(sz+64) as *u8; let e1: *u8 = sys_mmap(sz+64) as *u8 48 let wire: *u8 = sys_mmap(4194304) as *u8 49 let blk: *i64 = sys_mmap(512) as *i64; let mv: *i64 = sys_mmap(128) as *i64 50 let est: *i64 = sys_mmap(64) as *i64; let probs: *i64 = sys_mmap(4096) as *i64 51 let rcbuf: *u8 = sys_mmap(2097152) as *u8; let t8c: *i64 = sys_mmap(8192) as *i64 52 let rctx: *i64 = sys_mmap(128) as *i64 53 vc_t8_init(t8c) 54 let BW: i64 = NW/16; let BH: i64 = NH/16 55 // per-MB MV planes for the median predictor (raster scan: left/top/topright available) 56 let mvxp: *i64 = sys_mmap(BW*BH*8) as *i64 57 let mvyp: *i64 = sys_mmap(BW*BH*8) as *i64 58 let qp: i64 = 22 59 zero(e0, sz) 60 var ePrev: *u8 = e0; var eCur: *u8 = e1 61 // keyframe 62 seedctxe(rctx, EMODE, est, probs, rcbuf, t8c) 63 var nb: i64 = vv_enc_rct8(yuv, ePrev, eCur, NW, NH, qp, 1, qp*188, wire, 4194304, blk, mv, rctx) 64 var tE: *u8 = ePrev; ePrev = eCur; eCur = tE 65 var totBytes: i64=0; var totMv: i64=0; var totMed: i64=0; var totGol: i64=0; var totCoded: i64=0 66 var f: i64=1 67 while f<12 { 68 let cur: *u8 = ((yuv as i64) + f*FB) as *u8 69 // 1) REAL encode (recon-chained) -> real frame bytes. NOW: rct9 LEAN + retuned thresh qp*94 (vcv-10) 70 seedctxe(rctx, EMODE, est, probs, rcbuf, t8c) 71 nb = vv_enc_rct9(cur, ePrev, eCur, NW, NH, qp, qp*94, wire, 4194304, blk, mv, rctx) 72 if nb <= 0 { gw("enc fail -> RED\n" as *u8); return 1 } 73 // 2) MV census on the SAME ref (ePrev): mirror the skip gate + the coder's 16x16 search 74 var mvA: i64=0; var mvM: i64=0; var mvG: i64=0; var ncoded: i64=0 75 var by: i64=0 76 while by<BH { var bx: i64=0 77 while bx<BW { 78 let mi: i64 = by*BW + bx 79 let zs: i64 = vm_sad_zero(cur, ePrev, NW, bx, by, 16) 80 if zs < qp*94 { 81 mvxp[mi]=0; mvyp[mi]=0 // skip MB: contributes (0,0) to neighbours (H.264-style) 82 } else { 83 vm_search_q(cur, ePrev, NW, NH, bx, by, 16, 16, mv, qp, vmscr3) 84 // median predictor from left/top/topright (0,0) outside 85 var lx: i64=0; var ly: i64=0; var tx: i64=0; var ty: i64=0; var rx: i64=0; var ry: i64=0 86 if bx > 0 { lx = mvxp[mi-1]; ly = mvyp[mi-1] } 87 if by > 0 { tx = mvxp[mi-BW]; ty = mvyp[mi-BW] } 88 if by > 0 { if bx < BW-1 { rx = mvxp[mi-BW+1]; ry = mvyp[mi-BW+1] } } 89 let px: i64 = med3(lx, tx, rx) 90 let py: i64 = med3(ly, ty, ry) 91 mvA = mvA + vbits(mv[0]) + vbits(mv[1]) 92 mvM = mvM + vbits(mv[0]-px) + vbits(mv[1]-py) 93 mvG = mvG + gbits(mv[0]-px) + gbits(mv[1]-py) 94 mvxp[mi]=mv[0]; mvyp[mi]=mv[1] 95 ncoded = ncoded + 1 96 } 97 bx=bx+1 } by=by+1 } 98 totBytes = totBytes + nb; totMv = totMv + mvA; totMed = totMed + mvM; totGol = totGol + mvG 99 totCoded = totCoded + ncoded 100 // WIRE DECOMPOSITION: [ylen][ulen][vlen] header + per-stream CAVLC/range split (buf[0..1] = cavlc_end) 101 let yb: i64 = vv_rd_u32b(wire, 0) 102 let ub: i64 = vv_rd_u32b(wire, 4) 103 let vb: i64 = vv_rd_u32b(wire, 8) 104 let ys: *u8 = ((wire as i64) + 12) as *u8 105 let ycav: i64 = (ys[0] & 0xff) | ((ys[1] & 0xff) << 8) 106 gw("f" as *u8); gn(f); gw(" bytes=" as *u8); gn(nb) 107 gw(" [Y=" as *u8); gn(yb); gw(" (hdr" as *u8); gn(ycav); gw("+res" as *u8); gn(yb-ycav) 108 gw(") U=" as *u8); gn(ub); gw(" V=" as *u8); gn(vb); gw("]" as *u8) 109 gw(" coded=" as *u8); gn(ncoded) 110 gw(" mvbits=" as *u8); gn(mvA); gw("\n" as *u8) 111 tE = ePrev; ePrev = eCur; eCur = tE 112 f=f+1 113 } 114 gw("== TOTALS (11 P frames) ==\n" as *u8) 115 gw(" P bytes=" as *u8); gn(totBytes); gw(" coded MBs=" as *u8); gn(totCoded); gw("\n" as *u8) 116 gw(" MV bits ACTUAL (abs ve_vput) = " as *u8); gn(totMv) 117 gw(" = " as *u8); gn(totMv*1000/(totBytes*8)); gw("permille of P bytes\n" as *u8) 118 gw(" MV bits MEDIAN-PRED same VLC = " as *u8); gn(totMed) 119 gw(" (saves " as *u8); gn((totMv-totMed)*1000/(totBytes*8)); gw("permille of P bytes)\n" as *u8) 120 gw(" MV bits MEDIAN-PRED golomb = " as *u8); gn(totGol) 121 gw(" (saves " as *u8); gn((totMv-totGol)*1000/(totBytes*8)); gw("permille of P bytes)\n" as *u8) 122 gw("(16x16-level census: partition sub-MVs ignored -> real share is HIGHER; prize is a floor)\n" as *u8) 123 return 0 124}