code wiki / (root) / nx_h264_cabac_mb_gate.nx

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}