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}