nx_h264_cabac_mb_gate.nx source
↩ module page · 163 lines · 7598 B
1// nx_h264_cabac_mb_gate.nx -- teeth for the I-slice macroblock syntax layer.
2//
3// The STRONGEST thing provable here without a CABAC encoder is an EXHAUSTIVE round-trip over the
4// whole mb_type space: every I_16x16 mb_type must decompose into (predMode, cbpChroma, cbpLuma) and
5// recompose to itself. That validates the Table 9-36 field packing exactly -- which is the part most
6// likely to be silently wrong -- across all 24 values, not a sample.
7// Range teeth on the bitstream-driven readers prove they cannot emit an illegal symbol.
8// Spec conformance of the BIN ORDER still needs a real stream; not claimed here.
9import "nx_syscalls.nx"
10import "nx_h264_cabac.nx"
11import "nx_h264_cabac_mb.nx"
12import "nx_gate_verdict.nx"
13
14func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
15func gn(v: i64) -> i64 {
16 let b: *u8 = sys_mmap(28)
17 var m: i64 = v
18 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m }
19 let t: *u8 = sys_mmap(28)
20 var k: i64 = 0
21 if m == 0 { t[0] = 48 as u8; k = 1 }
22 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
23 var i: i64 = 0
24 while i < k { b[i] = t[k-1-i]; i = i + 1 }
25 sys_write(1, b, k)
26 return 0
27}
28
29func main(argc: i64, argv: *i64) -> i64 {
30 var pass: i64 = 0
31 var tot: i64 = 0
32 let cab: *i64 = sys_mmap(8*16) as *i64
33 let ctx: *i64 = sys_mmap(8*2048) as *i64
34 let rlps: *i64 = sys_mmap(8*256) as *i64
35 let tlps: *i64 = sys_mmap(8*128) as *i64
36 let tmps: *i64 = sys_mmap(8*128) as *i64
37 let data: *u8 = sys_mmap(4096)
38 let ca: *i64 = sys_mmap(8*8) as *i64
39 let cb: *i64 = sys_mmap(8*8) as *i64
40 cab_load_tables(rlps, tlps, tmps)
41 var i: i64 = 0
42 while i < 4096 { data[i] = 170 as u8; i = i + 1 }
43
44 // T1: EXHAUSTIVE round-trip of the mb_type field packing, all 24 I_16x16 values
45 tot = tot + 1
46 var bad: i64 = 0
47 var m: i64 = 1
48 while m <= 24 {
49 let pm: i64 = cmb_i16_predmode(m)
50 let cc: i64 = cmb_i16_cbpchroma(m)
51 let cl: i64 = cmb_i16_cbpluma(m)
52 var clbit: i64 = 0
53 if cl == 15 { clbit = 1 }
54 let re: i64 = 1 + pm + 4 * cc + 12 * clbit
55 if re != m { bad = bad + 1 }
56 if pm < 0 { bad = bad + 1 }
57 if pm > 3 { bad = bad + 1 }
58 if cc < 0 { bad = bad + 1 }
59 if cc > 2 { bad = bad + 1 }
60 m = m + 1
61 }
62 if bad == 0 { pass = pass + 1; gw("T1 mb_type field packing round-trips for ALL 24 I_16x16 values OK\n\x00" as *u8) } else { gw("T1 FAIL mismatches=\x00" as *u8); gn(bad); gw("\n\x00" as *u8) }
63
64 // T2: the I_16x16 range boundaries, and refusal outside it (matched pair)
65 tot = tot + 1
66 if cmb_is_i16x16(0) == 0 { if cmb_is_i16x16(1) == 1 { if cmb_is_i16x16(24) == 1 { if cmb_is_i16x16(25) == 0 {
67 if cmb_i16_predmode(0) < 0 { if cmb_i16_predmode(25) < 0 {
68 pass = pass + 1; gw("T2 I_16x16 range 1..24, I_NxN(0) and I_PCM(25) excluded + refused OK\n\x00" as *u8) } } } } } }
69
70 // T3: cbpLuma is 0 or 15 only, and flips exactly at mb_type 13
71 tot = tot + 1
72 if cmb_i16_cbpluma(12) == 0 { if cmb_i16_cbpluma(13) == 15 { if cmb_i16_cbpluma(24) == 15 {
73 pass = pass + 1; gw("T3 cbpLuma is 0 below mb_type 13 and 15 at/above it OK\n\x00" as *u8) } } }
74
75 // T4: rem_intra4x4_pred_mode is 3 bits -> can NEVER leave 0..7
76 tot = tot + 1
77 var out_of_range: i64 = 0
78 var t: i64 = 0
79 while t < 24 {
80 cab_init(cab, data, t, 4096)
81 let v: i64 = cmb_rem_i4(cab, ctx, rlps, tlps, tmps)
82 if v < 0 { out_of_range = out_of_range + 1 }
83 if v > 7 { out_of_range = out_of_range + 1 }
84 t = t + 1
85 }
86 if out_of_range == 0 { pass = pass + 1; gw("T4 rem_intra4x4 stays within 0..7 across 24 stream offsets OK\n\x00" as *u8) } else { gw("T4 FAIL out_of_range=\x00" as *u8); gn(out_of_range); gw("\n\x00" as *u8) }
87
88 // T5: intra_chroma_pred_mode is TU cMax=3 -> can NEVER exceed 3
89 tot = tot + 1
90 out_of_range = 0
91 t = 0
92 while t < 24 {
93 cab_init(cab, data, t, 4096)
94 let v: i64 = cmb_chroma_pred(cab, ctx, rlps, tlps, tmps, 0, 0)
95 if v < 0 { out_of_range = out_of_range + 1 }
96 if v > 3 { out_of_range = out_of_range + 1 }
97 t = t + 1
98 }
99 if out_of_range == 0 { pass = pass + 1; gw("T5 intra_chroma_pred_mode stays within 0..3 OK\n\x00" as *u8) } else { gw("T5 FAIL out=\x00" as *u8); gn(out_of_range); gw("\n\x00" as *u8) }
100
101 // T6: cbp luma is a 4-bit field -> 0..15, and chroma is 0..2
102 tot = tot + 1
103 out_of_range = 0
104 i = 0
105 while i < 4 { ca[i] = 0; cb[i] = 0; i = i + 1 }
106 t = 0
107 while t < 16 {
108 cab_init(cab, data, t, 4096)
109 let l: i64 = cmb_cbp_luma(cab, ctx, rlps, tlps, tmps, ca, cb)
110 if l < 0 { out_of_range = out_of_range + 1 }
111 if l > 15 { out_of_range = out_of_range + 1 }
112 cab_init(cab, data, t, 4096)
113 let c: i64 = cmb_cbp_chroma(cab, ctx, rlps, tlps, tmps, 0, 0, 0, 0)
114 if c < 0 { out_of_range = out_of_range + 1 }
115 if c > 2 { out_of_range = out_of_range + 1 }
116 t = t + 1
117 }
118 if out_of_range == 0 { pass = pass + 1; gw("T6 cbp luma 0..15 and chroma 0..2 across 16 offsets OK\n\x00" as *u8) } else { gw("T6 FAIL out=\x00" as *u8); gn(out_of_range); gw("\n\x00" as *u8) }
119
120 // T7: mb_type decoding never returns a value outside {0, 1..24, 25}
121 tot = tot + 1
122 out_of_range = 0
123 t = 0
124 while t < 24 {
125 cab_init(cab, data, t, 4096)
126 let mt: i64 = cmb_mbtype_i(cab, ctx, rlps, tlps, tmps, 0, 0)
127 if mt < 0 { out_of_range = out_of_range + 1 }
128 if mt > 25 { out_of_range = out_of_range + 1 }
129 t = t + 1
130 }
131 if out_of_range == 0 { pass = pass + 1; gw("T7 mb_type always within 0..25 across 24 stream offsets OK\n\x00" as *u8) } else { gw("T7 FAIL out=\x00" as *u8); gn(out_of_range); gw("\n\x00" as *u8) }
132
133 // T8: ctxBlockCat plumbing -- EXHAUSTIVE over cats 0..4 against Table 9-34.
134 // A wrong context base decodes garbage SILENTLY, so assert every value.
135 tot = tot + 1
136 var cbad: i64 = 0
137 if cmb_sig_base(0) != 105 { cbad = cbad + 1 }
138 if cmb_sig_base(1) != 120 { cbad = cbad + 1 }
139 if cmb_sig_base(2) != 134 { cbad = cbad + 1 }
140 if cmb_sig_base(3) != 149 { cbad = cbad + 1 }
141 if cmb_sig_base(4) != 152 { cbad = cbad + 1 }
142 if cmb_last_base(0) != 166 { cbad = cbad + 1 }
143 if cmb_last_base(4) != 213 { cbad = cbad + 1 }
144 if cmb_abs_base(0) != 227 { cbad = cbad + 1 }
145 if cmb_abs_base(4) != 266 { cbad = cbad + 1 }
146 if cmb_cat_maxcoeff(0) != 16 { cbad = cbad + 1 }
147 if cmb_cat_maxcoeff(1) != 15 { cbad = cbad + 1 }
148 if cmb_cat_maxcoeff(3) != 4 { cbad = cbad + 1 }
149 if cbad == 0 { pass = pass + 1; gw("T8 ctxBlockCat bases exhaustive vs Table 9-34 OK\n\x00" as *u8) } else { gw("T8 FAIL wrong bases=\x00" as *u8); gn(cbad); gw("\n\x00" as *u8) }
150
151 // T9: out-of-range ctxBlockCat is REFUSED by every accessor (matched control)
152 tot = tot + 1
153 if cmb_sig_base(0 - 1) < 0 { if cmb_sig_base(5) < 0 { if cmb_abs_base(5) < 0 { if cmb_cat_maxcoeff(9) < 0 {
154 if cmb_coded_block_flag(cab, ctx, rlps, tlps, tmps, 9, 0, 0) < 0 {
155 pass = pass + 1; gw("T9 out-of-range ctxBlockCat refused by every accessor OK\n\x00" as *u8) } } } } }
156
157 let ctr: *i64 = gv_ctr()
158 ctr[0] = pass
159 ctr[1] = tot
160 let rc: i64 = gv_verdict("H264-CABAC-MB" as *u8, ctr, "I-slice mb_type packing round-trips exhaustively and every syntax reader stays inside its legal range (bin-order conformance NOT claimed: needs a real stream)" as *u8)
161 sys_exit(rc)
162 return rc
163}