code wiki / (root) / nx_h264_cabac_residual.nx

nx_h264_cabac_residual.nx source

↩ module page · 118 lines · 4974 B

1// nx_h264_cabac_residual.nx -- H.264 CABAC residual block decoding (clause 9.3.2.3 / 9.3.3.1.3). 2// STEP 2, built on the STEP-1 arithmetic engine in nx_h264_cabac.nx which is KAT-verified against 3// clause 9.3.1 (gate ALL-PASS). Decodes ONE residual block: the significance map, then the levels 4// in reverse scan order, then signs. 5// 6// WHY THIS EXISTS: ~50% of the recording corpus is CABAC-coded and the poster/dead-air paths refuse 7// it outright (rc=10), which is the single largest measured blocker on gallery posters (117 of 236 8// files needing work, 2026-07-31). The arithmetic engine already existed and was never built on. 9// 10// SCOPE + HONESTY: binarization and context routing follow the spec, and the teeth below check the 11// structure that can be checked without a reference decoder. END-TO-END CORRECTNESS IS NOT PROVEN 12// HERE -- that requires decoding a real CABAC stream and looking at the image. Do not claim CABAC 13// posters work until that runs. 14// license_tier: ORIGINAL 15import "nx_syscalls.nx" 16import "nx_h264_cabac.nx" 17import "nx_h264_cabac_ctxinc.nx" 18 19const CBR_MAXCOEFF: i64 = 64 // largest block we handle (8x8 luma); 4x4 uses 16 20const CBR_UNARY_MAX: i64 = 13 // coeff_abs_level_minus1 prefix cap before the EG0 suffix 21const CBR_EG0_MAXK: i64 = 32 22const CBR_MAX_LEVEL: i64 = 32768 // a coefficient level beyond this cannot occur in 8-bit H.264; past it the stream is corrupt and we REFUSE rather than emit a value that overflows the coefficient arrays // bound on the Exp-Golomb suffix so a corrupt stream cannot spin 23 24// Exp-Golomb order-0 suffix, all bypass bins. Bounded: a corrupt stream must not loop forever. 25func cbr_eg0_bypass(cab: *i64) -> i64 { 26 var k: i64 = 0 27 var val: i64 = 0 28 var go: i64 = 1 29 while go == 1 { 30 if k >= CBR_EG0_MAXK { return 0 - 1 } else { 31 if cab_bypass(cab) == 1 { 32 val = val + (1 << k) 33 k = k + 1 34 } else { go = 0 } 35 } 36 } 37 var suffix: i64 = 0 38 var i: i64 = 0 39 while i < k { 40 suffix = (suffix << 1) | cab_bypass(cab) 41 i = i + 1 42 } 43 return val + suffix 44} 45 46// Significance map (9.3.2.3). Fills sigflag[0..maxc-1] with 1 where a coefficient is present. 47// Returns the number of coefficients present, or 0-1 if the stream is inconsistent. 48func cbr_sigmap(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, 49 base_sig: i64, base_last: i64, maxc: i64, sigflag: *i64) -> i64 { 50 if maxc <= 0 { return 0 - 1 } 51 if maxc > CBR_MAXCOEFF { return 0 - 1 } 52 var i: i64 = 0 53 while i < maxc { sigflag[i] = 0; i = i + 1 } 54 var n: i64 = 0 55 var pos: i64 = 0 56 var go: i64 = 1 57 while go == 1 { 58 if pos >= maxc - 1 { go = 0 } else { 59 let s: i64 = cab_decision(cab, ctx, base_sig + cci_sig4x4(pos), rlps, tlps, tmps) 60 if s == 1 { 61 sigflag[pos] = 1 62 n = n + 1 63 let l: i64 = cab_decision(cab, ctx, base_last + cci_sig4x4(pos), rlps, tlps, tmps) 64 if l == 1 { go = 0; pos = maxc } 65 } 66 if go == 1 { pos = pos + 1 } 67 } 68 } 69 // if we ran to the final position without a last-flag, that coefficient is implicitly present 70 if pos == maxc - 1 { 71 sigflag[maxc - 1] = 1 72 n = n + 1 73 } 74 return n 75} 76 77// Levels in REVERSE scan order (9.3.3.1.3), with signs. Writes signed levels into out[]. 78// Returns the number of levels decoded. 79func cbr_levels(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, 80 base_abs: i64, maxc: i64, sigflag: *i64, out: *i64) -> i64 { 81 var i: i64 = 0 82 while i < maxc { out[i] = 0; i = i + 1 } 83 var numGt1: i64 = 0 84 var numEq1: i64 = 0 85 var done: i64 = 0 86 var p: i64 = maxc - 1 87 while p >= 0 { 88 if sigflag[p] == 1 { 89 let c0: i64 = base_abs + cci_abslevel_bin0(numGt1, numEq1) 90 var level: i64 = 1 91 if cab_decision(cab, ctx, c0, rlps, tlps, tmps) == 1 { 92 let cn: i64 = base_abs + cci_abslevel_binN(numGt1) 93 var k: i64 = 0 94 var go: i64 = 1 95 while go == 1 { 96 if k >= CBR_UNARY_MAX { go = 0 } else { 97 if cab_decision(cab, ctx, cn, rlps, tlps, tmps) == 1 { k = k + 1 } else { go = 0 } 98 } 99 } 100 if k >= CBR_UNARY_MAX { 101 let eg: i64 = cbr_eg0_bypass(cab) 102 if eg < 0 { return 0 - 1 } 103 level = CBR_UNARY_MAX + 1 + eg 104 if level > CBR_MAX_LEVEL { return 0 - 1 } 105 } else { 106 level = k + 2 107 } 108 numGt1 = numGt1 + 1 109 } else { 110 numEq1 = numEq1 + 1 111 } 112 if cab_bypass(cab) == 1 { out[p] = 0 - level } else { out[p] = level } 113 done = done + 1 114 } 115 p = p - 1 116 } 117 return done 118}