code wiki / _hdl_build / nx_vcodec_subpel_gate.nx

nx_vcodec_subpel_gate.nx source

↩ module page · 74 lines · 4095 B

1// nx_vcodec_subpel_gate.nx -- proves the half-pel wiring is REALIZED inside the transmittable codec: a frame shifted 2// by exactly 0.5px is encoded inter, the decoder reconstructs it BIT-EXACT, and the half-pel predictor slashes the 3// residual the codec must code (vs what integer-only prediction would leave) -- the in-codec sub-pixel q/bit win. 4import "nx_syscalls.nx" 5import "nx_gate_emit_lib.nx" 6import "nx_vcodec.nx" 7 8func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 9func frame_equal(a: *u8, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n { if a[i]!=b[i] { return 0 } i=i+1 } return 1 } 10func frame_maxerr(a: *u8, b: *u8, n: i64) -> i64 { var m: i64=0; var i: i64=0; while i<n { let e: i64=g_abs((a[i] as i64)-(b[i] as i64)); if e>m { m=e } i=i+1 } return m } 11 12func main() -> i64 { 13 g_puts("nx_vcodec sub-pixel gate (half-pel realized IN the codec, BIT-EXACT + q/bit)\n" as *u8) 14 var pass: i64 = 0; var total: i64 = 0 15 let W: i64 = 48; let H: i64 = 32; let N: i64 = W*H 16 let QP: i64 = 12; let SAD_THRESH: i64 = 64 17 18 let f0: *u8 = sys_mmap(N) as *u8 19 let f1: *u8 = sys_mmap(N) as *u8 20 let recon0: *u8 = sys_mmap(N) as *u8 21 let enc1: *u8 = sys_mmap(N) as *u8 22 let dec1: *u8 = sys_mmap(N) as *u8 23 let stream: *u8 = sys_mmap(8192) as *u8 24 let blk: *i64 = sys_mmap(16*8) as *i64 25 let mv: *i64 = sys_mmap(2*8) as *i64 26 27 // textured reference (neighbours differ so sub-pixel motion is real), f1 = f0 shifted +0.5px in x 28 var y: i64 = 0 29 while y < H { var x: i64 = 0 30 while x < W { f0[y*W+x] = (40 + ((x*11 + y*7) % 120)) as u8; x = x + 1 } y = y + 1 } 31 y = 0 32 while y < H { var x: i64 = 0 33 while x < W - 1 { f1[y*W+x] = (((f0[y*W+x] as i64) + (f0[y*W+(x+1)] as i64) + 1) / 2) as u8; x = x + 1 } 34 f1[y*W + (W-1)] = f0[y*W + (W-1)]; y = y + 1 } 35 36 // keyframe f0 -> shared reference recon0 (encoder + decoder agree) 37 vc_enc_frame_packed(f0, recon0, recon0, W, H, QP, 1, SAD_THRESH, stream, blk, mv) 38 vc_dec_frame_packed(recon0, recon0, W, H, QP, stream, blk, mv) // recon0 now = the reference both sides hold 39 40 // encode the 0.5px-shifted frame INTER, then decode independently 41 let bits: i64 = vc_enc_frame_packed(f1, recon0, enc1, W, H, QP, 0, SAD_THRESH, stream, blk, mv) 42 let bytes: i64 = (bits + 7) / 8 43 vc_dec_frame_packed(recon0, dec1, W, H, QP, stream, blk, mv) 44 45 let eq: i64 = frame_equal(enc1, dec1, N) 46 let q: i64 = frame_maxerr(enc1, f1, N) 47 48 // evidence: residual the codec would face WITHOUT half-pel (integer prediction) vs WITH (half-pel), over an interior MB 49 let cx: i64 = 0; let cy: i64 = 0 50 var int_sad: i64 = 0 51 var half_sad: i64 = 0 52 var ry: i64 = 0 53 while ry < 16 { 54 var rx: i64 = 0 55 while rx < 16 { 56 let cur: i64 = f1[(cy+ry)*W + (cx+rx)] as i64 57 int_sad = int_sad + g_abs(cur - hp_pixel(recon0, W, cx+rx, cy+ry, 0, 0)) 58 half_sad = half_sad + g_abs(cur - hp_pixel(recon0, W, cx+rx, cy+ry, 1, 0)) 59 rx = rx + 1 60 } 61 ry = ry + 1 62 } 63 64 g_puts(" [measure] 0.5px-shift inter stream=" as *u8); g_pn(bytes); g_puts(" B recon max-err vs original=" as *u8); g_pn(q); g_puts("\n" as *u8) 65 g_puts(" [measure] one MB residual SAD: integer-pred=" as *u8); g_pn(int_sad); g_puts(" half-pel-pred=" as *u8); g_pn(half_sad); g_puts(" (the bits half-pel saves)\n" as *u8) 66 67 pass = pass + g_check("0.5px-shift frame round-trips BIT-EXACT through the codec (decoder == encoder)" as *u8, eq); total=total+1 68 pass = pass + g_check("reconstruction faithful (max-err <= 16, normal QP=12 lossy on a real residual)" as *u8, q <= 16); total=total+1 69 pass = pass + g_check("codec's half-pel slashes the residual integer-pred would leave (>= 4x smaller)" as *u8, half_sad * 4 < int_sad); total=total+1 70 71 g_puts("---- vcodec sub-pixel gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 72 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 73 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 74}