code wiki / (root) / nx_h264_residual.nx

nx_h264_residual.nx source

↩ module page · 186 lines · 6402 B

1// nx_h264_residual.nx -- CAVLC residual 4x4 block assembler (rung 4c-v, spec 9.2). 2// Ties the four VLC primitives into a scan-order coefficient block, and its 3// inverse encoder so the whole thing is round-trip-gated SOVEREIGNLY. 4// decode: coeff_token -> (TotalCoeff,TrailingOnes); trailing-one signs; levels 5// (suffixLength init + first-level +2 offset); total_zeros; run_before 6// distribution; reverse-scan placement -> coeff[scan]. 7// encode: analyse coeff[] -> tc/t1/levels/runs/total_zeros -> emit (exact inverse). 8// Coverage is bounded by the filled VLC subsets (full tables fill later; the real 9// I-frame decode is the capstone oracle). Scan-order output; raster conversion 10// (inverse zigzag) is a tiny separate step. 11// 12// genealogy_id: itu_t_h264_sec9_2_residual_block 13// lineage_id: coeff_token+signs+levels+total_zeros+run_before+reverse_scan 14// license_tier: ORIGINAL 15import "nx_syscalls.nx" 16import "nx_h264_bits.nx" 17import "nx_h264_bitwriter.nx" 18import "nx_h264_cavlc_level.nx" 19import "nx_h264_cavlc_enc.nx" 20import "nx_h264_coeff_token.nx" 21import "nx_h264_total_zeros.nx" 22import "nx_h264_run_before.nx" 23 24// decode a residual block into coeff[0..max_num_coeff) (scan order). returns TotalCoeff, or -1 on table miss. 25func nx_h264_residual_decode(br: *BitReader, max_num_coeff: i64, nC: i64, coeff: *i64) -> i64 { 26 var z: i64 = 0 27 while z < max_num_coeff { coeff[z] = 0; z = z + 1 } 28 let ct: *i64 = br.ct 29 if nx_coeff_token_decode_ctx(br, nC, ct) == 0 { return 0 - 1 } 30 let tc: i64 = ct[0] 31 let t1: i64 = ct[1] 32 if tc == 0 { return 0 } 33 let level: *i64 = br.level 34 let run: *i64 = br.run 35 var sl: i64 = 0 36 if tc > 10 { if t1 < 3 { sl = 1 } } 37 var i: i64 = 0 38 while i < tc { 39 if i < t1 { 40 let s: i64 = br_read_bit(br) 41 if s == 0 { level[i] = 1 } 42 if s == 1 { level[i] = 0 - 1 } 43 } 44 if i >= t1 { 45 var off: i64 = 0 46 if i == t1 { if t1 < 3 { off = 2 } } 47 let lv: i64 = nx_cavlc_read_level_off(br, sl, off) 48 level[i] = lv 49 if sl == 0 { sl = 1 } 50 var al: i64 = lv 51 if al < 0 { al = 0 - al } 52 if al > (3 << (sl - 1)) { if sl < 6 { sl = sl + 1 } } 53 } 54 i = i + 1 55 } 56 var total_zeros: i64 = 0 57 if tc < max_num_coeff { total_zeros = nx_total_zeros_decode(br, tc) } 58 var zeros_left: i64 = total_zeros 59 i = 0 60 while i < tc - 1 { 61 var rb: i64 = 0 62 if zeros_left > 0 { rb = nx_run_before_decode(br, zeros_left); zeros_left = zeros_left - rb } 63 run[i] = rb 64 i = i + 1 65 } 66 run[tc - 1] = zeros_left 67 var coeff_num: i64 = 0 - 1 68 i = tc - 1 69 while i >= 0 { 70 coeff_num = coeff_num + run[i] + 1 71 coeff[coeff_num] = level[i] 72 i = i - 1 73 } 74 return tc 75} 76 77// decode a 2x2 chroma DC block (maxNumCoeff=4, nC=-1 tables) into out[0..3] (scan order). 78func nx_h264_residual_decode_cdc(br: *BitReader, out: *i64) -> i64 { 79 out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0 80 let ct: *i64 = br.ct 81 if nx_coeff_token_decode_cdc(br, ct) == 0 { return 0 - 1 } 82 let tc: i64 = ct[0] 83 let t1: i64 = ct[1] 84 if tc == 0 { return 0 } 85 let level: *i64 = br.level 86 let run: *i64 = br.run 87 var sl: i64 = 0 88 var i: i64 = 0 89 while i < tc { 90 if i < t1 { 91 let s: i64 = br_read_bit(br) 92 if s == 0 { level[i] = 1 } 93 if s == 1 { level[i] = 0 - 1 } 94 } 95 if i >= t1 { 96 var off: i64 = 0 97 if i == t1 { if t1 < 3 { off = 2 } } 98 let lv: i64 = nx_cavlc_read_level_off(br, sl, off) 99 level[i] = lv 100 if sl == 0 { sl = 1 } 101 var al: i64 = lv 102 if al < 0 { al = 0 - al } 103 if al > (3 << (sl - 1)) { if sl < 6 { sl = sl + 1 } } 104 } 105 i = i + 1 106 } 107 var total_zeros: i64 = 0 108 if tc < 4 { total_zeros = nx_total_zeros_decode_cdc(br, tc) } 109 var zeros_left: i64 = total_zeros 110 i = 0 111 while i < tc - 1 { 112 var rb: i64 = 0 113 if zeros_left > 0 { rb = nx_run_before_decode(br, zeros_left); zeros_left = zeros_left - rb } 114 run[i] = rb 115 i = i + 1 116 } 117 run[tc - 1] = zeros_left 118 var coeff_num: i64 = 0 - 1 119 i = tc - 1 120 while i >= 0 { 121 coeff_num = coeff_num + run[i] + 1 122 out[coeff_num] = level[i] 123 i = i - 1 124 } 125 return tc 126} 127 128// encode coeff[0..max_num_coeff) (scan order) as a CAVLC residual block. 129func nx_h264_residual_encode(bw: *BitWriter, coeff: *i64, max_num_coeff: i64, nC: i64) -> i64 { 130 let pos: *i64 = sys_mmap(32 * 8) as *i64 131 let val: *i64 = sys_mmap(32 * 8) as *i64 132 var tc: i64 = 0 133 var p: i64 = 0 134 while p < max_num_coeff { 135 if coeff[p] != 0 { pos[tc] = p; val[tc] = coeff[p]; tc = tc + 1 } 136 p = p + 1 137 } 138 // trailing ones: from highest scan pos, count |val|==1 up to 3 139 var t1: i64 = 0 140 var stop: i64 = 0 141 var k: i64 = tc - 1 142 while k >= 0 { 143 if stop == 0 { 144 var a: i64 = val[k] 145 if a < 0 { a = 0 - a } 146 if a != 1 { stop = 1 } 147 if stop == 0 { if t1 == 3 { stop = 1 } } 148 if stop == 0 { t1 = t1 + 1 } 149 } 150 k = k - 1 151 } 152 nx_coeff_token_encode(bw, tc, t1) 153 if tc == 0 { return 0 } 154 var sl: i64 = 0 155 if tc > 10 { if t1 < 3 { sl = 1 } } 156 var i: i64 = 0 157 while i < tc { 158 let lv: i64 = val[tc - 1 - i] 159 if i < t1 { 160 if lv > 0 { bw_write_bit(bw, 0) } 161 if lv < 0 { bw_write_bit(bw, 1) } 162 } 163 if i >= t1 { 164 var off: i64 = 0 165 if i == t1 { if t1 < 3 { off = 2 } } 166 nx_cavlc_encode_level_off(bw, lv, sl, off) 167 if sl == 0 { sl = 1 } 168 var al: i64 = lv 169 if al < 0 { al = 0 - al } 170 if al > (3 << (sl - 1)) { if sl < 6 { sl = sl + 1 } } 171 } 172 i = i + 1 173 } 174 var total_zeros: i64 = 0 175 if tc >= 1 { total_zeros = pos[tc - 1] - (tc - 1) } 176 if tc < max_num_coeff { nx_total_zeros_encode(bw, tc, total_zeros) } 177 var zeros_left: i64 = total_zeros 178 i = 0 179 while i < tc - 1 { 180 let hi: i64 = tc - 1 - i 181 let rb: i64 = pos[hi] - pos[hi - 1] - 1 182 if zeros_left > 0 { nx_run_before_encode(bw, zeros_left, rb); zeros_left = zeros_left - rb } 183 i = i + 1 184 } 185 return tc 186}