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}