code wiki / _hdl_build / nx_h264_iframe.nx
nx_h264_iframe.nx source
↩ module page · 496 lines · 20764 B
1// nx_h264_iframe.nx -- reusable CAVLC I-slice -> YUV420 decode driver (STEP 3 core for the cam poster).
2// Lifts the proven full-frame reconstruction from nx_h264_decode_frame.nx into a callable function that
3// takes an already-extracted, de-emulated IDR slice RBSP + parsed SPS/PPS + output planes, decodes every
4// macroblock (I_4x4 / I_16x16 / I_PCM), and reconstructs Y/U/V. Two engineering fixes vs the original main:
5// (1) uses CODED MB dims (mbW=sps[4]+1, mbH=sps[5]+1) so non-16-aligned crops (e.g. 1080) decode fully;
6// (2) HOISTS all per-call scratch out of the recon kernels (the toolchain's sys_mmap has no munmap; a
7// per-MB mmap would exhaust the kernel map_count on a full-HD frame) -> bounded, constant map count.
8// Deblocking is intentionally omitted here (a downscaled poster averages block edges away); add for full res.
9// LIB (no main). license_tier: ORIGINAL genealogy_id: itu_t_h264_islice_cavlc_recon (lifted from decode_frame)
10import "nx_syscalls.nx"
11import "nx_h264_bits.nx"
12import "nx_h264_slice.nx"
13import "nx_h264_mb.nx"
14import "nx_h264_mb_pred.nx"
15import "nx_h264_coeff_token.nx"
16import "nx_h264_cavlc_level.nx"
17import "nx_h264_residual.nx"
18import "nx_h264_nc.nx"
19import "nx_h264_zigzag.nx"
20import "nx_h264_hadamard.nx"
21import "nx_h264_dequant.nx"
22import "nx_h264_idct.nx"
23import "nx_h264_intra16.nx"
24import "nx_h264_intra.nx"
25import "nx_h264_chroma_pred.nx"
26import "nx_h264_chroma.nx"
27
28// shared recon scratch layout (i64 offsets into one buffer; recon calls are strictly sequential)
29const SC_PRED: i64 = 0 // 256 (i16 pred) / 64 (chroma)
30const SC_TOP: i64 = 256 // up to 16
31const SC_LEFT: i64 = 288 // up to 16
32const SC_SCAN: i64 = 320 // 16
33const SC_RAST: i64 = 336 // 16
34const SC_DQ: i64 = 352 // 16
35const SC_DCY: i64 = 368 // 16 (I16 luma DC scaled)
36const SC_NA: i64 = 384 // 6
37const SC_CC: i64 = 392 // 4
38const SC_DCC: i64 = 400 // 4
39const SC_IDCT: i64 = 408 // 16 words: nx_idct4x4 scratch, hoisted 2026-08-01 (SC_WORDS=512, so 408+16 fits)
40const SC_WORDS: i64 = 512
41
42func scp(sc: *i64, off: i64) -> *i64 { return ((sc as i64) + off * 8) as *i64 }
43
44// decode one luma 4x4 residual block (nC neighbour context). bx,by absolute 4x4 coords.
45func dec_luma(br: *BitReader, lumaTC: *i64, lbW: i64, bx: i64, by: i64, maxc: i64, coeff: *i64) -> i64 {
46 var nA: i64 = 0
47 var avA: i64 = 0
48 if bx > 0 { nA = lumaTC[by * lbW + (bx - 1)]; avA = 1 }
49 var nB: i64 = 0
50 var avB: i64 = 0
51 if by > 0 { nB = lumaTC[(by - 1) * lbW + bx]; avB = 1 }
52 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
53 let tc: i64 = nx_h264_residual_decode(br, maxc, nC, coeff)
54 lumaTC[by * lbW + bx] = tc
55 return tc
56}
57
58func dec_chroma_ac(br: *BitReader, cTC: *i64, cbW: i64, cbx: i64, cby: i64, coeff: *i64) -> i64 {
59 var nA: i64 = 0
60 var avA: i64 = 0
61 if cbx > 0 { nA = cTC[cby * cbW + (cbx - 1)]; avA = 1 }
62 var nB: i64 = 0
63 var avB: i64 = 0
64 if cby > 0 { nB = cTC[(cby - 1) * cbW + cbx]; avB = 1 }
65 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
66 let tc: i64 = nx_h264_residual_decode(br, 15, nC, coeff)
67 cTC[cby * cbW + cbx] = tc
68 return tc
69}
70
71func chroma_qpc(qpL: i64, cqo: i64) -> i64 {
72 var q: i64 = qpL + cqo
73 if q < 0 { q = 0 }
74 if q > 51 { q = 51 }
75 return nx_h264_chroma_qp(q)
76}
77
78// I_16x16 luma DC -> scaled dcY[16] written into sc[SC_DCY..].
79func i16_dc_scale_h(dcblk: *i64, qp: i64, sc: *i64) -> i64 {
80 let dcras: *i64 = scp(sc, SC_SCAN)
81 nx_h264_inv_zigzag4x4(dcblk, dcras)
82 nx_h264_hadamard4x4(dcras)
83 let na: *i64 = scp(sc, SC_NA)
84 na[0]=10; na[1]=11; na[2]=13; na[3]=14; na[4]=16; na[5]=18
85 let dcY: *i64 = scp(sc, SC_DCY)
86 let ls: i64 = 16 * na[qp % 6]
87 let sh6: i64 = qp / 6
88 var qi: i64 = 0
89 while qi < 16 {
90 var v: i64 = 0
91 if qp >= 36 { v = (dcras[qi] * ls) << (sh6 - 6) }
92 if qp < 36 { v = asr(dcras[qi] * ls + (1 << (5 - sh6)), 6 - sh6) }
93 dcY[qi] = v
94 qi = qi + 1
95 }
96 return 0
97}
98
99func recon_i16_luma_h(yf: *u8, W: i64, px: i64, py: i64, predMode: i64, sc: *i64, acstore: *i64, qp: i64) -> i64 {
100 var aT: i64 = 0
101 if py > 0 { aT = 1 }
102 var aL: i64 = 0
103 if px > 0 { aL = 1 }
104 let top: *i64 = scp(sc, SC_TOP)
105 let left: *i64 = scp(sc, SC_LEFT)
106 var k: i64 = 0
107 while k < 16 {
108 var tv: i64 = 0
109 if aT == 1 { tv = yf[(py-1)*W + px + k] as i64 }
110 top[k] = tv
111 var lv: i64 = 0
112 if aL == 1 { lv = yf[(py+k)*W + px - 1] as i64 }
113 left[k] = lv
114 k = k + 1
115 }
116 var tl: i64 = 0
117 if aT == 1 { if aL == 1 { tl = yf[(py-1)*W + px - 1] as i64 } }
118 let pred: *i64 = scp(sc, SC_PRED)
119 nx_intra16x16_pred_full(predMode, top, left, tl, aT, aL, pred)
120 let scan: *i64 = scp(sc, SC_SCAN)
121 let dq: *i64 = scp(sc, SC_DQ)
122 let dcY: *i64 = scp(sc, SC_DCY)
123 let rast: *i64 = scp(sc, SC_RAST)
124 var br: i64 = 0
125 while br < 4 {
126 var bc: i64 = 0
127 while bc < 4 {
128 let r: i64 = br * 4 + bc
129 var z: i64 = 0
130 while z < 16 { scan[z] = acstore[r*16 + z]; z = z + 1 }
131 nx_h264_inv_zigzag4x4(scan, rast)
132 nx_h264_dequant4x4(rast, qp, dq)
133 dq[0] = dcY[r]
134 nx_idct4x4_s(dq, scp(sc, SC_IDCT))
135 var py4: i64 = 0
136 while py4 < 4 {
137 var px4: i64 = 0
138 while px4 < 4 {
139 var val: i64 = pred[(br*4 + py4)*16 + (bc*4 + px4)] + dq[py4*4 + px4]
140 if val < 0 { val = 0 }
141 if val > 255 { val = 255 }
142 yf[(py + br*4 + py4)*W + (px + bc*4 + px4)] = val as u8
143 px4 = px4 + 1
144 }
145 py4 = py4 + 1
146 }
147 bc = bc + 1
148 }
149 br = br + 1
150 }
151 return 0
152}
153
154func recon_i4_block_h(yf: *u8, W: i64, bpx: i64, bpy: i64, mode: i64, aT: i64, aL: i64, aTL: i64, aTR: i64, coeffscan: *i64, qp: i64, sc: *i64) -> i64 {
155 let top: *i64 = scp(sc, SC_TOP)
156 let left: *i64 = scp(sc, SC_LEFT)
157 var k: i64 = 0
158 while k < 4 {
159 var tv: i64 = 0
160 if aT == 1 { tv = yf[(bpy-1)*W + bpx + k] as i64 }
161 top[k] = tv
162 var lv: i64 = 0
163 if aL == 1 { lv = yf[(bpy+k)*W + bpx - 1] as i64 }
164 left[k] = lv
165 k = k + 1
166 }
167 k = 0
168 while k < 4 {
169 var tv: i64 = top[3]
170 if aTR == 1 { tv = yf[(bpy-1)*W + bpx + 4 + k] as i64 }
171 if aT == 0 { tv = 0 }
172 top[4 + k] = tv
173 k = k + 1
174 }
175 var tl: i64 = 0
176 if aTL == 1 { tl = yf[(bpy-1)*W + bpx - 1] as i64 }
177 let pred: *i64 = scp(sc, SC_PRED)
178 nx_intra4x4_pred_full(mode, top, left, tl, aT, aL, pred)
179 let rast: *i64 = scp(sc, SC_RAST)
180 nx_h264_inv_zigzag4x4(coeffscan, rast)
181 let dq: *i64 = scp(sc, SC_DQ)
182 nx_h264_dequant4x4(rast, qp, dq)
183 nx_idct4x4(dq)
184 var yy: i64 = 0
185 while yy < 4 {
186 var xx: i64 = 0
187 while xx < 4 {
188 var val: i64 = pred[yy*4 + xx] + dq[yy*4 + xx]
189 if val < 0 { val = 0 }
190 if val > 255 { val = 255 }
191 yf[(bpy + yy)*W + (bpx + xx)] = val as u8
192 xx = xx + 1
193 }
194 yy = yy + 1
195 }
196 return 0
197}
198
199func recon_chroma_comp_h(cf: *u8, cW: i64, cpx: i64, cpy: i64, predMode: i64, cdc: *i64, acstore: *i64, qpc: i64, availT: i64, availL: i64, sc: *i64) -> i64 {
200 let top: *i64 = scp(sc, SC_TOP)
201 let left: *i64 = scp(sc, SC_LEFT)
202 var k: i64 = 0
203 while k < 8 {
204 var tv: i64 = 0
205 if availT == 1 { tv = cf[(cpy-1)*cW + cpx + k] as i64 }
206 top[k] = tv
207 var lv: i64 = 0
208 if availL == 1 { lv = cf[(cpy+k)*cW + cpx - 1] as i64 }
209 left[k] = lv
210 k = k + 1
211 }
212 var tl: i64 = 0
213 if availT == 1 { if availL == 1 { tl = cf[(cpy-1)*cW + cpx - 1] as i64 } }
214 let pred: *i64 = scp(sc, SC_PRED)
215 nx_intra_chroma_pred(predMode, top, left, tl, availT, availL, pred)
216 let cc: *i64 = scp(sc, SC_CC)
217 var di: i64 = 0
218 while di < 4 { cc[di] = cdc[di]; di = di + 1 }
219 let dcC: *i64 = scp(sc, SC_DCC)
220 nx_h264_chroma_dc_scale(cc, qpc, dcC)
221 let scan: *i64 = scp(sc, SC_SCAN)
222 let rast: *i64 = scp(sc, SC_RAST)
223 let dq: *i64 = scp(sc, SC_DQ)
224 var by: i64 = 0
225 while by < 2 {
226 var bx: i64 = 0
227 while bx < 2 {
228 let blk: i64 = by*2 + bx
229 var z: i64 = 0
230 while z < 16 { scan[z] = acstore[blk*16 + z]; z = z + 1 }
231 nx_h264_inv_zigzag4x4(scan, rast)
232 nx_h264_dequant4x4(rast, qpc, dq)
233 dq[0] = dcC[blk]
234 nx_idct4x4_s(dq, scp(sc, SC_IDCT))
235 var yy: i64 = 0
236 while yy < 4 {
237 var xx: i64 = 0
238 while xx < 4 {
239 var val: i64 = pred[(by*4+yy)*8 + (bx*4+xx)] + dq[yy*4 + xx]
240 if val < 0 { val = 0 }
241 if val > 255 { val = 255 }
242 cf[(cpy + by*4 + yy)*cW + (cpx + bx*4 + xx)] = val as u8
243 xx = xx + 1
244 }
245 yy = yy + 1
246 }
247 bx = bx + 1
248 }
249 by = by + 1
250 }
251 return 0
252}
253
254// Decode a single CAVLC I-slice (all MBs) into yf/uf/vf. Caller: mbW=sps[4]+1, mbH=sps[5]+1 (coded);
255// yf sized (mbW*16)*(mbH*16), uf/vf sized (mbW*8)*(mbH*8); planes pre-zeroed by caller.
256// Returns 1 iff all MBs parsed and the reader landed at the rbsp end; else 0 (desync / partial).
257func nx_h264_decode_iframe(sl_dst: *u8, sl_rbsp: i64, ntype: i64, sps: *i64, pps: *i64, yf: *u8, uf: *u8, vf: *u8, mbW: i64, mbH: i64) -> i64 {
258 let W: i64 = mbW * 16
259 let cpW: i64 = mbW * 8
260 let lbW: i64 = mbW * 4
261 let lbH: i64 = mbH * 4
262 let cbW: i64 = mbW * 2
263 let cbH: i64 = mbH * 2
264 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
265 br_init(sbr, sl_dst, sl_rbsp)
266 let sh: *i64 = sys_mmap(64) as *i64
267 nx_h264_parse_slice_header_br(sbr, ntype & 31, (ntype >> 5) & 3, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh)
268 var qp: i64 = sh[7]
269
270 // hoisted state (allocate ONCE)
271 let sc: *i64 = sys_mmap(SC_WORDS * 8) as *i64
272 let lumaTC: *i64 = sys_mmap(lbW * lbH * 8) as *i64
273 let i4m: *i64 = sys_mmap(lbW * lbH * 8) as *i64
274 let decoded: *i64 = sys_mmap(lbW * lbH * 8) as *i64
275 let uTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
276 let vTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
277 var z: i64 = 0
278 while z < lbW * lbH { lumaTC[z] = 0; i4m[z] = 2; decoded[z] = 0; z = z + 1 }
279 z = 0
280 while z < cbW * cbH { uTC[z] = 0; vTC[z] = 0; z = z + 1 }
281 let acstore: *i64 = sys_mmap(16 * 16 * 8) as *i64
282 let ucstore: *i64 = sys_mmap(4 * 16 * 8) as *i64
283 let vcstore: *i64 = sys_mmap(4 * 16 * 8) as *i64
284 let coeff: *i64 = sys_mmap(32 * 8) as *i64
285 let der: *i64 = sys_mmap(32 * 8) as *i64
286 let dcblk: *i64 = sys_mmap(16 * 8) as *i64
287 let ucdc: *i64 = sys_mmap(8 * 8) as *i64
288 let vcdc: *i64 = sys_mmap(8 * 8) as *i64
289 let modes: *i64 = sys_mmap(24 * 8) as *i64
290 let bx4: *i64 = sys_mmap(16 * 8) as *i64
291 let by4: *i64 = sys_mmap(16 * 8) as *i64
292 bx4[0]=0; by4[0]=0; bx4[1]=1; by4[1]=0; bx4[2]=0; by4[2]=1; bx4[3]=1; by4[3]=1
293 bx4[4]=2; by4[4]=0; bx4[5]=3; by4[5]=0; bx4[6]=2; by4[6]=1; bx4[7]=3; by4[7]=1
294 bx4[8]=0; by4[8]=2; bx4[9]=1; by4[9]=2; bx4[10]=0; by4[10]=3; bx4[11]=1; by4[11]=3
295 bx4[12]=2; by4[12]=2; bx4[13]=3; by4[13]=2; bx4[14]=2; by4[14]=3; bx4[15]=3; by4[15]=3
296
297 var ok: i64 = 1
298 var mbAddr: i64 = 0
299 let totalMB: i64 = mbW * mbH
300 while mbAddr < totalMB {
301 let mbX: i64 = mbAddr % mbW
302 let mbY: i64 = mbAddr / mbW
303 let mb_type: i64 = nx_h264_mb_parse_itype(sbr)
304 if mb_type < 0 { ok = 0; mbAddr = totalMB }
305 if ok == 1 { if mb_type > 25 { ok = 0; mbAddr = totalMB } }
306 if ok == 1 {
307 let cls: i64 = nx_h264_mb_type_class(mb_type)
308
309 if cls == 2 {
310 // I_PCM: byte-align, consume 384 raw samples (pixels not reconstructed -> rare), neighbours=16
311 br_align(sbr)
312 var pp: i64 = 0
313 while pp < 384 { br_read_bits(sbr, 8); pp = pp + 1 }
314 var bl: i64 = 0
315 while bl < 16 { lumaTC[(mbY*4 + by4[bl]) * lbW + (mbX*4 + bx4[bl])] = 16; bl = bl + 1 }
316 var cc: i64 = 0
317 while cc < 4 {
318 uTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 16
319 vTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 16
320 cc = cc + 1
321 }
322 }
323
324 if cls == 1 {
325 nx_h264_i16x16_derive(mb_type, der)
326 let cbpL: i64 = der[2]
327 let cbpC: i64 = der[1]
328 let chroma_pred: i64 = br_read_ue(sbr)
329 let mqd: i64 = br_read_se(sbr)
330 qp = (qp + mqd + 52) % 52
331 let bx0: i64 = mbX * 4
332 let by0: i64 = mbY * 4
333 var nA: i64 = 0
334 var avA: i64 = 0
335 if bx0 > 0 { nA = lumaTC[by0 * lbW + (bx0 - 1)]; avA = 1 }
336 var nB: i64 = 0
337 var avB: i64 = 0
338 if by0 > 0 { nB = lumaTC[(by0 - 1) * lbW + bx0]; avB = 1 }
339 let nCdc: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
340 nx_h264_residual_decode(sbr, 16, nCdc, dcblk)
341 z = 0
342 while z < 256 { acstore[z] = 0; z = z + 1 }
343 var bl: i64 = 0
344 while bl < 16 {
345 let abx: i64 = bx0 + bx4[bl]
346 let aby: i64 = by0 + by4[bl]
347 let r: i64 = by4[bl] * 4 + bx4[bl]
348 i4m[aby * lbW + abx] = 2
349 if cbpL != 0 {
350 dec_luma(sbr, lumaTC, lbW, abx, aby, 15, coeff)
351 z = 0
352 while z < 15 { acstore[r*16 + 1 + z] = coeff[z]; z = z + 1 }
353 }
354 if cbpL == 0 { lumaTC[aby * lbW + abx] = 0 }
355 decoded[aby * lbW + abx] = 1
356 bl = bl + 1
357 }
358 i16_dc_scale_h(dcblk, qp, sc)
359 recon_i16_luma_h(yf, W, mbX * 16, mbY * 16, der[0], sc, acstore, qp)
360 z = 0
361 while z < 4 { ucdc[z] = 0; vcdc[z] = 0; z = z + 1 }
362 z = 0
363 while z < 64 { ucstore[z] = 0; vcstore[z] = 0; z = z + 1 }
364 if cbpC != 0 {
365 nx_h264_residual_decode_cdc(sbr, ucdc)
366 nx_h264_residual_decode_cdc(sbr, vcdc)
367 if cbpC == 2 {
368 var cc: i64 = 0
369 while cc < 4 {
370 dec_chroma_ac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
371 z = 0
372 while z < 15 { ucstore[cc*16 + 1 + z] = coeff[z]; z = z + 1 }
373 cc = cc + 1
374 }
375 cc = 0
376 while cc < 4 {
377 dec_chroma_ac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
378 z = 0
379 while z < 15 { vcstore[cc*16 + 1 + z] = coeff[z]; z = z + 1 }
380 cc = cc + 1
381 }
382 }
383 }
384 if cbpC == 0 {
385 var cc: i64 = 0
386 while cc < 4 { uTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 0; vTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 0; cc = cc + 1 }
387 }
388 var qpi16: i64 = qp + pps[9]
389 if qpi16 < 0 { qpi16 = 0 }
390 if qpi16 > 51 { qpi16 = 51 }
391 let qpc16: i64 = nx_h264_chroma_qp(qpi16)
392 var caT16: i64 = 0
393 if mbY > 0 { caT16 = 1 }
394 var caL16: i64 = 0
395 if mbX > 0 { caL16 = 1 }
396 recon_chroma_comp_h(uf, cpW, mbX*8, mbY*8, chroma_pred, ucdc, ucstore, qpc16, caT16, caL16, sc)
397 recon_chroma_comp_h(vf, cpW, mbX*8, mbY*8, chroma_pred, vcdc, vcstore, qpc16, caT16, caL16, sc)
398 }
399
400 if cls == 0 {
401 nx_h264_parse_inxn_predmodes(sbr, modes)
402 let cbp: i64 = nx_h264_decode_cbp_intra(sbr)
403 let cbpL: i64 = cbp & 15
404 let cbpC: i64 = (cbp >> 4) & 3
405 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
406 let bx0: i64 = mbX * 4
407 let by0: i64 = mbY * 4
408 var bl: i64 = 0
409 while bl < 16 {
410 let abx: i64 = bx0 + bx4[bl]
411 let aby: i64 = by0 + by4[bl]
412 let bpx: i64 = mbX * 16 + bx4[bl] * 4
413 let bpy: i64 = mbY * 16 + by4[bl] * 4
414 var avAm: i64 = 0
415 if abx > 0 { if decoded[aby*lbW + abx - 1] == 1 { avAm = 1 } }
416 var avBm: i64 = 0
417 if aby > 0 { if decoded[(aby-1)*lbW + abx] == 1 { avBm = 1 } }
418 var predMode: i64 = 2
419 if avAm == 1 { if avBm == 1 {
420 let ma: i64 = i4m[aby*lbW + abx - 1]
421 let mbb: i64 = i4m[(aby-1)*lbW + abx]
422 predMode = ma
423 if mbb < ma { predMode = mbb }
424 } }
425 var mode: i64 = predMode
426 if modes[bl] >= 0 {
427 let rem: i64 = modes[bl]
428 if rem < predMode { mode = rem }
429 if rem >= predMode { mode = rem + 1 }
430 }
431 i4m[aby*lbW + abx] = mode
432 let i8: i64 = bl / 4
433 z = 0
434 while z < 16 { coeff[z] = 0; z = z + 1 }
435 if ((cbpL >> i8) & 1) != 0 {
436 dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff)
437 }
438 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby*lbW + abx] = 0 }
439 var aT: i64 = 0
440 if avBm == 1 { aT = 1 }
441 var aL: i64 = 0
442 if avAm == 1 { aL = 1 }
443 var aTL: i64 = 0
444 if abx > 0 { if aby > 0 { if decoded[(aby-1)*lbW + abx - 1] == 1 { aTL = 1 } } }
445 var aTR: i64 = 0
446 if aby > 0 { if abx + 1 < lbW { if decoded[(aby-1)*lbW + abx + 1] == 1 { aTR = 1 } } }
447 recon_i4_block_h(yf, W, bpx, bpy, mode, aT, aL, aTL, aTR, coeff, qp, sc)
448 decoded[aby*lbW + abx] = 1
449 bl = bl + 1
450 }
451 z = 0
452 while z < 4 { ucdc[z] = 0; vcdc[z] = 0; z = z + 1 }
453 z = 0
454 while z < 64 { ucstore[z] = 0; vcstore[z] = 0; z = z + 1 }
455 if cbpC != 0 {
456 nx_h264_residual_decode_cdc(sbr, ucdc)
457 nx_h264_residual_decode_cdc(sbr, vcdc)
458 if cbpC == 2 {
459 var cc: i64 = 0
460 while cc < 4 {
461 dec_chroma_ac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
462 z = 0
463 while z < 15 { ucstore[cc*16 + 1 + z] = coeff[z]; z = z + 1 }
464 cc = cc + 1
465 }
466 cc = 0
467 while cc < 4 {
468 dec_chroma_ac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
469 z = 0
470 while z < 15 { vcstore[cc*16 + 1 + z] = coeff[z]; z = z + 1 }
471 cc = cc + 1
472 }
473 }
474 }
475 if cbpC == 0 {
476 var cc: i64 = 0
477 while cc < 4 { uTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 0; vTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 0; cc = cc + 1 }
478 }
479 var qpi4: i64 = qp + pps[9]
480 if qpi4 < 0 { qpi4 = 0 }
481 if qpi4 > 51 { qpi4 = 51 }
482 let qpc4: i64 = nx_h264_chroma_qp(qpi4)
483 var caT4: i64 = 0
484 if mbY > 0 { caT4 = 1 }
485 var caL4: i64 = 0
486 if mbX > 0 { caL4 = 1 }
487 recon_chroma_comp_h(uf, cpW, mbX*8, mbY*8, modes[16], ucdc, ucstore, qpc4, caT4, caL4, sc)
488 recon_chroma_comp_h(vf, cpW, mbX*8, mbY*8, modes[16], vcdc, vcstore, qpc4, caT4, caL4, sc)
489 }
490
491 mbAddr = mbAddr + 1
492 }
493 }
494 if ok == 1 { if mbAddr == totalMB { if sbr.byte_pos >= sl_rbsp - 2 { return 1 } } }
495 return 0
496}