code wiki / _hdl_build / nx_vmvpred_gate.nx

nx_vmvpred_gate.nx source

↩ module page · 74 lines · 3937 B

1// nx_vmvpred_gate.nx -- proves + MEASURES MV prediction (nx_vmvpred): on a realistic motion field (a camera pan with a 2// couple of differently-moving object blocks), coding MVs as residuals from the median neighbour predictor costs far 3// fewer bits than coding them absolutely. Uses the codec's real varint MV cost (ve_zze/ve_blen). 4import "nx_syscalls.nx" 5import "nx_gate_emit_lib.nx" 6import "nx_vmvpred.nx" 7import "nx_ventropy.nx" 8 9func vbits(v: i64) -> i64 { return 5 + ve_blen(ve_zze(v)) } // bits one varint MV component costs (codec's coder) 10 11func main() -> i64 { 12 g_puts("nx_vmvpred gate (median MV prediction cuts MV bits on a pan, MEASURED)\n" as *u8) 13 var pass: i64 = 0; var total: i64 = 0 14 let BW: i64 = 6; let BH: i64 = 4; let NB: i64 = BW*BH // 6x4 = 24 macroblocks 15 16 // realistic motion field: a (3,1) camera pan everywhere, EXCEPT a 2x2 "object" at (bx 2..3, by 1..2) moving (3,5), 17 // and one fast block at (5,0) moving (8,-2). Stored as mvx[NB], mvy[NB] in raster order. 18 let mvx: *i64 = sys_mmap(NB*8) as *i64 19 let mvy: *i64 = sys_mmap(NB*8) as *i64 20 var by: i64 = 0 21 while by < BH { 22 var bx: i64 = 0 23 while bx < BW { 24 let i: i64 = by*BW + bx 25 var dx: i64 = 3; var dy: i64 = 1 // the pan 26 if bx >= 2 { if bx <= 3 { if by >= 1 { if by <= 2 { dx = 3; dy = 5 } } } } // object 27 if bx == 5 { if by == 0 { dx = 8; dy = 0 - 2 } } // fast block 28 mvx[i] = dx; mvy[i] = dy 29 bx = bx + 1 30 } 31 by = by + 1 32 } 33 34 let L: *i64 = sys_mmap(2*8) as *i64 35 let T: *i64 = sys_mmap(2*8) as *i64 36 let TR: *i64 = sys_mmap(2*8) as *i64 37 let pred: *i64 = sys_mmap(2*8) as *i64 38 39 var abs_bits: i64 = 0 40 var diff_bits: i64 = 0 41 by = 0 42 while by < BH { 43 var bx: i64 = 0 44 while bx < BW { 45 let i: i64 = by*BW + bx 46 // neighbours (0 if off-grid): L=left, T=top, TR=top-right 47 L[0]=0; L[1]=0; T[0]=0; T[1]=0; TR[0]=0; TR[1]=0 48 if bx > 0 { L[0]=mvx[i-1]; L[1]=mvy[i-1] } 49 if by > 0 { T[0]=mvx[i-BW]; T[1]=mvy[i-BW] } 50 if by > 0 { if bx < BW-1 { TR[0]=mvx[i-BW+1]; TR[1]=mvy[i-BW+1] } } 51 mvp_predict(L, T, TR, pred) 52 abs_bits = abs_bits + vbits(mvx[i]) + vbits(mvy[i]) 53 diff_bits = diff_bits + vbits(mvx[i]-pred[0]) + vbits(mvy[i]-pred[1]) 54 bx = bx + 1 55 } 56 by = by + 1 57 } 58 59 // separate the varint's fixed 5-bit length prefix (per component, unavoidable) from the magnitude bits MVP targets 60 let prefix: i64 = 5 * 2 * NB 61 let abs_mag: i64 = abs_bits - prefix 62 let pred_mag: i64 = diff_bits - prefix 63 64 g_puts(" [measure] MV coding over " as *u8); g_pn(NB); g_puts(" blocks: absolute=" as *u8); g_pn(abs_bits); g_puts(" bits predicted=" as *u8); g_pn(diff_bits); g_puts(" bits (total saving " as *u8); g_pn((abs_bits - diff_bits) * 100 / abs_bits); g_puts("%)\n" as *u8) 65 g_puts(" [measure] MV MAGNITUDE bits (ex the fixed 5-bit prefix): absolute=" as *u8); g_pn(abs_mag); g_puts(" predicted=" as *u8); g_pn(pred_mag); g_puts(" (saving " as *u8); g_pn((abs_mag - pred_mag) * 100 / abs_mag); g_puts("%)\n" as *u8) 66 67 pass = pass + g_check("predicted MV coding costs fewer bits than absolute" as *u8, diff_bits < abs_bits); total=total+1 68 pass = pass + g_check("MVP cuts MV MAGNITUDE bits >= 50% (its real effect; the fixed 5-bit prefix masks it in the total)" as *u8, pred_mag * 2 <= abs_mag); total=total+1 69 pass = pass + g_check("total MV-bit saving >= 20% even with the prefix overhead" as *u8, diff_bits * 5 <= abs_bits * 4); total=total+1 70 71 g_puts("---- vmvpred 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}