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}