nx_h264_pframe_recon.nx source
↩ module page · 1062 lines · 51708 B
1// nx_h264_pframe_recon.nx -- P-R4b: pixel-exact LUMA reconstruction of frame 1 (inter content).
2// Uses frame 0's PRE-deblock luma plane as the reference (ref_frame0.yuv -- proven byte-exact
3// equal to nx_h264_decode_frame's pre-deblock recon), reconstructs every SKIP + INTER macroblock by
4// motion-compensating each 4x4 block from the reference (per-4x4 MV from the grid) and adding the decoded
5// residual (inv-zigzag -> dequant -> 4x4 IDCT -> add+clip), then compares to ffmpeg's frame-1 PRE-deblock
6// luma (ref_frame1_nodeblock.yuv). Both sides skip deblocking, isolating MC+residual from the loop filter.
7// Intra-in-P macroblocks (179) are decoded for entropy sync but EXCLUDED from the pixel count (P-R4b-2).
8// Exit 0/1. Log knowledge/status/h264_pframe_recon.log. license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_mp4_demux.nx"
11import "nx_mp4_stbl.nx"
12import "nx_h264_bits.nx"
13import "nx_h264_sps.nx"
14import "nx_h264_pps.nx"
15import "nx_h264_nal.nx"
16import "nx_h264_slice.nx"
17import "nx_h264_mb.nx"
18import "nx_h264_mb_pred.nx"
19import "nx_h264_coeff_token.nx"
20import "nx_h264_cavlc_level.nx"
21import "nx_h264_residual.nx"
22import "nx_h264_nc.nx"
23import "nx_h264_pmb.nx"
24import "nx_h264_mvgrid.nx"
25import "nx_h264_idct.nx"
26import "nx_h264_dequant.nx"
27import "nx_h264_zigzag.nx"
28import "nx_h264_hadamard.nx"
29import "nx_h264_intra16.nx"
30import "nx_h264_intra.nx"
31import "nx_h264_intra_recon.nx"
32import "nx_h264_chroma.nx"
33import "nx_h264_chroma_pred.nx"
34import "nx_h264_deblock.nx"
35import "nx_h264_mc_luma.nx"
36
37func gp(fd: i64, s: *u8) -> i64 {
38 var n: i64 = 0
39 while s[n] != (0 as u8) { n = n + 1 }
40 sys_write(1, s, n); if fd > 0 { sys_write(fd, s, n) }
41 return 0
42}
43func gn(fd: i64, v: i64) -> i64 {
44 let bb: *u8 = sys_mmap(28); var m: i64 = v
45 if m < 0 { sys_write(1, "-\x00" as *u8, 1); if fd > 0 { sys_write(fd, "-\x00" as *u8, 1) } m = 0 - m }
46 let t: *u8 = sys_mmap(28); var k: i64 = 0
47 if m == 0 { t[0] = 48 as u8; k = 1 }
48 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
49 var i: i64 = 0
50 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
51 sys_write(1, bb, k); if fd > 0 { sys_write(fd, bb, k) }
52 return 0
53}
54func find_tag(b: *u8, start: i64, end: i64, s: *u8) -> i64 {
55 var i: i64 = start
56 while i + 4 <= end { if mp4_t4(b, i, s) == 1 { return i - 4 } i = i + 1 }
57 return 0 - 1
58}
59func dec_luma(br: *BitReader, lumaTC: *i64, lbW: i64, bx: i64, by: i64, maxc: i64, coeff: *i64) -> i64 {
60 var nA: i64 = 0
61 var avA: i64 = 0
62 if bx > 0 { nA = lumaTC[by * lbW + (bx - 1)]; avA = 1 }
63 var nB: i64 = 0
64 var avB: i64 = 0
65 if by > 0 { nB = lumaTC[(by - 1) * lbW + bx]; avB = 1 }
66 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
67 let tc: i64 = nx_h264_residual_decode(br, maxc, nC, coeff)
68 lumaTC[by * lbW + bx] = tc
69 return tc
70}
71func dec_cac(br: *BitReader, cTC: *i64, cbW: i64, cbx: i64, cby: i64, coeff: *i64) -> i64 {
72 var nA: i64 = 0
73 var avA: i64 = 0
74 if cbx > 0 { nA = cTC[cby * cbW + (cbx - 1)]; avA = 1 }
75 var nB: i64 = 0
76 var avB: i64 = 0
77 if cby > 0 { nB = cTC[(cby - 1) * cbW + cbx]; avB = 1 }
78 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
79 let tc: i64 = nx_h264_residual_decode(br, 15, nC, coeff)
80 cTC[cby * cbW + cbx] = tc
81 return tc
82}
83func read_ref(sbr: *BitReader, num_ref: i64) -> i64 {
84 if num_ref == 1 { return 0 }
85 if num_ref == 2 { let bbit: i64 = br_read_bit(sbr); return 1 - bbit }
86 return br_read_ue(sbr)
87}
88// Reconstruct one 4x4 luma block at picture pixel (bpx,bpy) of frame1: motion-compensate from the
89// reference plane with MV (mvx,mvy) [quarter-pel], add residual (coeffscan, qp) when hasRes, write to myY.
90func recon_inter_4x4(myY: *u8, W: i64, ref: *u8, Wr: i64, Hr: i64, bpx: i64, bpy: i64,
91 mvx: i64, mvy: i64, coeffscan: *i64, qp: i64, hasRes: i64) -> i64 {
92 let pred: *u8 = sys_mmap(16) as *u8
93 var yy: i64 = 0
94 while yy < 4 {
95 var xx: i64 = 0
96 while xx < 4 {
97 let fullX: i64 = (bpx + xx) + asr(mvx, 2)
98 let fracX: i64 = mvx & 3
99 let fullY: i64 = (bpy + yy) + asr(mvy, 2)
100 let fracY: i64 = mvy & 3
101 pred[yy * 4 + xx] = nx_h264_mc_luma_sample(ref, Wr, Hr, fullX, fullY, fracX, fracY) as u8
102 xx = xx + 1
103 }
104 yy = yy + 1
105 }
106 if hasRes == 0 {
107 yy = 0
108 while yy < 4 {
109 var xx: i64 = 0
110 while xx < 4 { myY[(bpy + yy) * W + (bpx + xx)] = pred[yy * 4 + xx]; xx = xx + 1 }
111 yy = yy + 1
112 }
113 return 0
114 }
115 let rast: *i64 = sys_mmap(16 * 8) as *i64
116 nx_h264_inv_zigzag4x4(coeffscan, rast)
117 let dq: *i64 = sys_mmap(16 * 8) as *i64
118 nx_h264_dequant4x4(rast, qp, dq)
119 nx_idct4x4(dq)
120 yy = 0
121 while yy < 4 {
122 var xx: i64 = 0
123 while xx < 4 {
124 var val: i64 = (pred[yy * 4 + xx] as i64) + dq[yy * 4 + xx]
125 if val < 0 { val = 0 }
126 if val > 255 { val = 255 }
127 myY[(bpy + yy) * W + (bpx + xx)] = val as u8
128 xx = xx + 1
129 }
130 yy = yy + 1
131 }
132 return 0
133}
134
135func cclamp(v: i64, hi: i64) -> i64 { if v < 0 { return 0 } if v > hi { return hi } return v }
136// one chroma sample (8.4.2.2.2): 1/8-pel bilinear from the reference chroma plane.
137func chroma_mc_sample(refC: *u8, cW: i64, cH: i64, cx: i64, cy: i64, mvx: i64, mvy: i64) -> i64 {
138 let xi: i64 = cx + asr(mvx, 3)
139 let yi: i64 = cy + asr(mvy, 3)
140 let xf: i64 = mvx & 7
141 let yf: i64 = mvy & 7
142 let x0: i64 = cclamp(xi, cW - 1)
143 let x1: i64 = cclamp(xi + 1, cW - 1)
144 let y0: i64 = cclamp(yi, cH - 1)
145 let y1: i64 = cclamp(yi + 1, cH - 1)
146 let A: i64 = refC[y0 * cW + x0] as i64
147 let B: i64 = refC[y0 * cW + x1] as i64
148 let C: i64 = refC[y1 * cW + x0] as i64
149 let D: i64 = refC[y1 * cW + x1] as i64
150 return ((8 - xf) * (8 - yf) * A + xf * (8 - yf) * B + (8 - xf) * yf * C + xf * yf * D + 32) >> 6
151}
152// reconstruct one chroma component (U or V) of one inter/skip MB: motion-compensate each of the 4
153// chroma 4x4 blocks (per-sample MV from the luma grid) + add residual (chroma DC 2x2 + AC), -> myC.
154// dc4 = 4 decoded chroma-DC levels (consumed by the scale); ac4[q*16+0..14] = the 15 AC per block q.
155func recon_chroma_inter_mb(myC: *u8, refC: *u8, cW: i64, cH: i64, mbX: i64, mbY: i64,
156 gmvx: *i64, gmvy: *i64, lbW: i64, dc4: *i64, ac4: *i64, cbpC: i64, QPc: i64) -> i64 {
157 let sdc: *i64 = sys_mmap(4 * 8) as *i64
158 if cbpC >= 1 { nx_h264_chroma_dc_scale(dc4, QPc, sdc) }
159 var q: i64 = 0
160 while q < 4 {
161 let bcx: i64 = mbX * 8 + (q % 2) * 4
162 let bcy: i64 = mbY * 8 + (q / 2) * 4
163 let pred: *i64 = sys_mmap(16 * 8) as *i64
164 var yy: i64 = 0
165 while yy < 4 {
166 var xx: i64 = 0
167 while xx < 4 {
168 let cx: i64 = bcx + xx
169 let cy: i64 = bcy + yy
170 let mvx: i64 = gmvx[(cy / 2) * lbW + (cx / 2)]
171 let mvy: i64 = gmvy[(cy / 2) * lbW + (cx / 2)]
172 pred[yy * 4 + xx] = chroma_mc_sample(refC, cW, cH, cx, cy, mvx, mvy)
173 xx = xx + 1
174 }
175 yy = yy + 1
176 }
177 if cbpC == 0 {
178 yy = 0
179 while yy < 4 {
180 var xx: i64 = 0
181 while xx < 4 { myC[(bcy + yy) * cW + (bcx + xx)] = pred[yy * 4 + xx] as u8; xx = xx + 1 }
182 yy = yy + 1
183 }
184 }
185 if cbpC >= 1 {
186 let scan: *i64 = sys_mmap(16 * 8) as *i64
187 var z2: i64 = 0
188 while z2 < 16 { scan[z2] = 0; z2 = z2 + 1 }
189 if cbpC == 2 { z2 = 0; while z2 < 15 { scan[1 + z2] = ac4[q * 16 + z2]; z2 = z2 + 1 } }
190 let rast: *i64 = sys_mmap(16 * 8) as *i64
191 nx_h264_inv_zigzag4x4(scan, rast)
192 let dq: *i64 = sys_mmap(16 * 8) as *i64
193 nx_h264_dequant4x4(rast, QPc, dq)
194 dq[0] = sdc[q]
195 nx_idct4x4(dq)
196 yy = 0
197 while yy < 4 {
198 var xx: i64 = 0
199 while xx < 4 {
200 var val: i64 = pred[yy * 4 + xx] + dq[yy * 4 + xx]
201 if val < 0 { val = 0 }
202 if val > 255 { val = 255 }
203 myC[(bcy + yy) * cW + (bcx + xx)] = val as u8
204 xx = xx + 1
205 }
206 yy = yy + 1
207 }
208 }
209 q = q + 1
210 }
211 return 0
212}
213
214// reconstruct one chroma component of an INTRA-in-P MB: intra chroma prediction (DC/H/V/Plane) from
215// reconstructed neighbours in myC + residual (chroma DC 2x2 + AC). mode = intra_chroma_pred_mode.
216func recon_chroma_intra_mb(myC: *u8, cW: i64, cH: i64, mbX: i64, mbY: i64, mode: i64,
217 availTop: i64, availLeft: i64, dc4: *i64, ac4: *i64, cbpC: i64, QPc: i64) -> i64 {
218 let bx0: i64 = mbX * 8
219 let by0: i64 = mbY * 8
220 let top: *i64 = sys_mmap(8 * 8) as *i64
221 let left: *i64 = sys_mmap(8 * 8) as *i64
222 var k: i64 = 0
223 while k < 8 {
224 var tv: i64 = 0
225 if availTop == 1 { tv = myC[(by0 - 1) * cW + (bx0 + k)] as i64 }
226 top[k] = tv
227 var lv: i64 = 0
228 if availLeft == 1 { lv = myC[(by0 + k) * cW + (bx0 - 1)] as i64 }
229 left[k] = lv
230 k = k + 1
231 }
232 var tl: i64 = 0
233 if availTop == 1 { if availLeft == 1 { tl = myC[(by0 - 1) * cW + (bx0 - 1)] as i64 } }
234 let pred: *i64 = sys_mmap(64 * 8) as *i64
235 nx_intra_chroma_pred(mode, top, left, tl, availTop, availLeft, pred)
236 let sdc: *i64 = sys_mmap(4 * 8) as *i64
237 if cbpC >= 1 { nx_h264_chroma_dc_scale(dc4, QPc, sdc) }
238 var q: i64 = 0
239 while q < 4 {
240 let qx: i64 = (q % 2) * 4
241 let qy: i64 = (q / 2) * 4
242 let p16: *i64 = sys_mmap(16 * 8) as *i64
243 var yy: i64 = 0
244 while yy < 4 {
245 var xx: i64 = 0
246 while xx < 4 { p16[yy * 4 + xx] = pred[(qy + yy) * 8 + (qx + xx)]; xx = xx + 1 }
247 yy = yy + 1
248 }
249 if cbpC == 0 {
250 yy = 0
251 while yy < 4 {
252 var xx: i64 = 0
253 while xx < 4 { myC[(by0 + qy + yy) * cW + (bx0 + qx + xx)] = p16[yy * 4 + xx] as u8; xx = xx + 1 }
254 yy = yy + 1
255 }
256 }
257 if cbpC >= 1 {
258 let scan: *i64 = sys_mmap(16 * 8) as *i64
259 var z2: i64 = 0
260 while z2 < 16 { scan[z2] = 0; z2 = z2 + 1 }
261 if cbpC == 2 { z2 = 0; while z2 < 15 { scan[1 + z2] = ac4[q * 16 + z2]; z2 = z2 + 1 } }
262 let rast: *i64 = sys_mmap(16 * 8) as *i64
263 nx_h264_inv_zigzag4x4(scan, rast)
264 let dq: *i64 = sys_mmap(16 * 8) as *i64
265 nx_h264_dequant4x4(rast, QPc, dq)
266 dq[0] = sdc[q]
267 nx_idct4x4(dq)
268 yy = 0
269 while yy < 4 {
270 var xx: i64 = 0
271 while xx < 4 {
272 var val: i64 = p16[yy * 4 + xx] + dq[yy * 4 + xx]
273 if val < 0 { val = 0 }
274 if val > 255 { val = 255 }
275 myC[(by0 + qy + yy) * cW + (bx0 + qx + xx)] = val as u8
276 xx = xx + 1
277 }
278 yy = yy + 1
279 }
280 }
281 q = q + 1
282 }
283 return 0
284}
285
286// P-frame boundary strength (8.7.2.1) for the edge between 4x4 blocks p and q (gref<0 == intra).
287// intra -> 4 if MB boundary else 3; else nonzero-coeff -> 2; else |mvDiff|>=4 (1 luma sample) -> 1; else 0.
288// (single reference list here, so the different-reference test never fires.)
289func p_bs(gref: *i64, gmvx: *i64, gmvy: *i64, lumaTC: *i64, pblk: i64, qblk: i64, mbBoundary: i64) -> i64 {
290 if gref[pblk] < 0 { if mbBoundary == 1 { return 4 } return 3 }
291 if gref[qblk] < 0 { if mbBoundary == 1 { return 4 } return 3 }
292 if lumaTC[pblk] > 0 { return 2 }
293 if lumaTC[qblk] > 0 { return 2 }
294 var dx: i64 = gmvx[pblk] - gmvx[qblk]
295 if dx < 0 { dx = 0 - dx }
296 var dy: i64 = gmvy[pblk] - gmvy[qblk]
297 if dy < 0 { dy = 0 - dy }
298 if dx >= 4 { return 1 }
299 if dy >= 4 { return 1 }
300 return 0
301}
302// In-loop luma deblock for a P-frame: per MB raster order, 4 vertical then 4 horizontal edges, each
303// split into four 4x4 segments with their own bS (p_bs). Reuses the PROVEN luma filters
304// (nx_deblock_luma_bs4 / nx_deblock_luma_edge). bS==0 segments are left untouched.
305func deblock_luma_p(yf: *u8, W: i64, mbW: i64, mbH: i64, mbQP: *i64,
306 gref: *i64, gmvx: *i64, gmvy: *i64, lumaTC: *i64, lbW: i64, bsHist: *i64) -> i64 {
307 let s: *i64 = sys_mmap(8 * 8) as *i64
308 let ve: *i64 = sys_mmap(8 * 8) as *i64
309 ve[0]=0; ve[1]=4; ve[2]=8; ve[3]=12
310 var dmy: i64 = 0
311 while dmy < mbH {
312 var dmx: i64 = 0
313 while dmx < mbW {
314 let px: i64 = dmx * 16
315 let py: i64 = dmy * 16
316 let qpMB: i64 = mbQP[dmy * mbW + dmx]
317 // ---- vertical edges ----
318 var ei: i64 = 0
319 while ei < 4 {
320 let eo: i64 = ve[ei]
321 let ex: i64 = px + eo
322 let qcol: i64 = dmx * 4 + eo / 4
323 var doit: i64 = 1
324 if eo == 0 { if dmx == 0 { doit = 0 } }
325 if doit == 1 {
326 var qpe: i64 = qpMB
327 if eo == 0 { qpe = (mbQP[dmy * mbW + (dmx - 1)] + qpMB + 1) >> 1 }
328 var mbb: i64 = 0
329 if eo == 0 { mbb = 1 }
330 var seg: i64 = 0
331 while seg < 4 {
332 let row4: i64 = dmy * 4 + seg
333 let qblk: i64 = row4 * lbW + qcol
334 let pblk: i64 = row4 * lbW + (qcol - 1)
335 let bs: i64 = p_bs(gref, gmvx, gmvy, lumaTC, pblk, qblk, mbb)
336 bsHist[bs] = bsHist[bs] + 1
337 if bs > 0 {
338 var r: i64 = 0
339 while r < 4 {
340 let ry: i64 = seg * 4 + r
341 let base: i64 = (py + ry) * W + ex
342 s[0] = yf[base - 4] as i64; s[1] = yf[base - 3] as i64; s[2] = yf[base - 2] as i64; s[3] = yf[base - 1] as i64
343 s[4] = yf[base] as i64; s[5] = yf[base + 1] as i64; s[6] = yf[base + 2] as i64; s[7] = yf[base + 3] as i64
344 if bs == 4 { nx_deblock_luma_bs4(s, qpe) }
345 if bs < 4 { nx_deblock_luma_edge(s, bs, qpe) }
346 yf[base - 3] = s[1] as u8; yf[base - 2] = s[2] as u8; yf[base - 1] = s[3] as u8
347 yf[base] = s[4] as u8; yf[base + 1] = s[5] as u8; yf[base + 2] = s[6] as u8
348 r = r + 1
349 }
350 }
351 seg = seg + 1
352 }
353 }
354 ei = ei + 1
355 }
356 // ---- horizontal edges ----
357 ei = 0
358 while ei < 4 {
359 let eo: i64 = ve[ei]
360 let ey: i64 = py + eo
361 let qrow: i64 = dmy * 4 + eo / 4
362 var doit: i64 = 1
363 if eo == 0 { if dmy == 0 { doit = 0 } }
364 if doit == 1 {
365 var qpe: i64 = qpMB
366 if eo == 0 { qpe = (mbQP[(dmy - 1) * mbW + dmx] + qpMB + 1) >> 1 }
367 var mbb: i64 = 0
368 if eo == 0 { mbb = 1 }
369 var seg: i64 = 0
370 while seg < 4 {
371 let col4: i64 = dmx * 4 + seg
372 let qblk: i64 = qrow * lbW + col4
373 let pblk: i64 = (qrow - 1) * lbW + col4
374 let bs: i64 = p_bs(gref, gmvx, gmvy, lumaTC, pblk, qblk, mbb)
375 bsHist[bs] = bsHist[bs] + 1
376 if bs > 0 {
377 var r: i64 = 0
378 while r < 4 {
379 let col: i64 = px + seg * 4 + r
380 s[0] = yf[(ey - 4) * W + col] as i64; s[1] = yf[(ey - 3) * W + col] as i64; s[2] = yf[(ey - 2) * W + col] as i64; s[3] = yf[(ey - 1) * W + col] as i64
381 s[4] = yf[ey * W + col] as i64; s[5] = yf[(ey + 1) * W + col] as i64; s[6] = yf[(ey + 2) * W + col] as i64; s[7] = yf[(ey + 3) * W + col] as i64
382 if bs == 4 { nx_deblock_luma_bs4(s, qpe) }
383 if bs < 4 { nx_deblock_luma_edge(s, bs, qpe) }
384 yf[(ey - 3) * W + col] = s[1] as u8; yf[(ey - 2) * W + col] = s[2] as u8; yf[(ey - 1) * W + col] = s[3] as u8
385 yf[ey * W + col] = s[4] as u8; yf[(ey + 1) * W + col] = s[5] as u8; yf[(ey + 2) * W + col] = s[6] as u8
386 r = r + 1
387 }
388 }
389 seg = seg + 1
390 }
391 }
392 ei = ei + 1
393 }
394 dmx = dmx + 1
395 }
396 dmy = dmy + 1
397 }
398 return 0
399}
400
401// chroma QP for a luma QP (Table 8-15 via offset), clipped.
402func cqp(lumaQP: i64, cqio: i64) -> i64 {
403 var q: i64 = lumaQP + cqio
404 if q < 0 { q = 0 }
405 if q > 51 { q = 51 }
406 return nx_h264_chroma_qp(q)
407}
408// In-loop CHROMA deblock for a P-frame (4:2:0): 2 vertical + 2 horizontal chroma edges per MB (x/y in
409// {0,4}). bS is the LUMA bS at the co-located luma 4x4 (each chroma sample maps to luma 2x; 2 chroma
410// samples per luma 4x4). qpc = chroma QP (avg of the two MBs' chroma QP at a MB boundary). Reuses p_bs +
411// the proven nx_deblock_chroma_edge.
412func deblock_chroma_p(myC: *u8, cW: i64, cH: i64, mbW: i64, mbH: i64, mbQP: *i64,
413 gref: *i64, gmvx: *i64, gmvy: *i64, lumaTC: *i64, lbW: i64, cqio: i64) -> i64 {
414 let s: *i64 = sys_mmap(8 * 8) as *i64
415 let ceo: *i64 = sys_mmap(2 * 8) as *i64
416 ceo[0] = 0; ceo[1] = 4
417 var dmy: i64 = 0
418 while dmy < mbH {
419 var dmx: i64 = 0
420 while dmx < mbW {
421 let qpThis: i64 = cqp(mbQP[dmy * mbW + dmx], cqio)
422 var ei: i64 = 0
423 while ei < 2 {
424 let ce: i64 = ceo[ei]
425 let cx: i64 = dmx * 8 + ce
426 let qcol: i64 = dmx * 4 + ce / 2
427 var doit: i64 = 1
428 if ce == 0 { if dmx == 0 { doit = 0 } }
429 if doit == 1 {
430 var qpc: i64 = qpThis
431 if ce == 0 { qpc = (cqp(mbQP[dmy * mbW + (dmx - 1)], cqio) + qpThis + 1) >> 1 }
432 var mbb: i64 = 0
433 if ce == 0 { mbb = 1 }
434 var r: i64 = 0
435 while r < 8 {
436 let cy: i64 = dmy * 8 + r
437 let row4: i64 = dmy * 4 + r / 2
438 let qblk: i64 = row4 * lbW + qcol
439 let pblk: i64 = row4 * lbW + (qcol - 1)
440 let bs: i64 = p_bs(gref, gmvx, gmvy, lumaTC, pblk, qblk, mbb)
441 if bs > 0 {
442 s[0] = myC[cy * cW + cx - 2] as i64
443 s[1] = myC[cy * cW + cx - 1] as i64
444 s[2] = myC[cy * cW + cx] as i64
445 s[3] = myC[cy * cW + cx + 1] as i64
446 nx_deblock_chroma_edge(s, bs, qpc)
447 myC[cy * cW + cx - 1] = s[1] as u8
448 myC[cy * cW + cx] = s[2] as u8
449 }
450 r = r + 1
451 }
452 }
453 ei = ei + 1
454 }
455 ei = 0
456 while ei < 2 {
457 let ce: i64 = ceo[ei]
458 let cy: i64 = dmy * 8 + ce
459 let qrow: i64 = dmy * 4 + ce / 2
460 var doit: i64 = 1
461 if ce == 0 { if dmy == 0 { doit = 0 } }
462 if doit == 1 {
463 var qpc: i64 = qpThis
464 if ce == 0 { qpc = (cqp(mbQP[(dmy - 1) * mbW + dmx], cqio) + qpThis + 1) >> 1 }
465 var mbb: i64 = 0
466 if ce == 0 { mbb = 1 }
467 var c: i64 = 0
468 while c < 8 {
469 let cx: i64 = dmx * 8 + c
470 let col4: i64 = dmx * 4 + c / 2
471 let qblk: i64 = qrow * lbW + col4
472 let pblk: i64 = (qrow - 1) * lbW + col4
473 let bs: i64 = p_bs(gref, gmvx, gmvy, lumaTC, pblk, qblk, mbb)
474 if bs > 0 {
475 s[0] = myC[(cy - 2) * cW + cx] as i64
476 s[1] = myC[(cy - 1) * cW + cx] as i64
477 s[2] = myC[cy * cW + cx] as i64
478 s[3] = myC[(cy + 1) * cW + cx] as i64
479 nx_deblock_chroma_edge(s, bs, qpc)
480 myC[(cy - 1) * cW + cx] = s[1] as u8
481 myC[cy * cW + cx] = s[2] as u8
482 }
483 c = c + 1
484 }
485 }
486 ei = ei + 1
487 }
488 dmx = dmx + 1
489 }
490 dmy = dmy + 1
491 }
492 return 0
493}
494
495func main() -> i64 {
496 let fd: i64 = sys_openat_append("knowledge/status/h264_pframe_recon.log\x00" as *u8, 0x1a4)
497 gp(fd, "H264-PFRAME-RECON (P-R4b luma + P-R5 chroma + P-R6 deblock vs ffmpeg)\n\x00" as *u8)
498 let szp: *i64 = sys_mmap(16) as *i64
499 let b: *u8 = sys_read_file("knowledge/staging/media/realtest.mp4\x00" as *u8, szp)
500 if (b as i64) == 0 { gp(fd, "no realtest.mp4\n\x00" as *u8); sys_exit(1); return 1 }
501 let len: i64 = szp[0]
502 let avcc: i64 = find_tag(b, 0, len, "avcC\x00" as *u8)
503 let pay: i64 = avcc + 8
504 let spsLen: i64 = (b[pay + 6] as i64) * 256 + (b[pay + 7] as i64)
505 let spsdst: *u8 = sys_mmap(spsLen + 16)
506 let spsrbsp: i64 = nx_h264_unescape_rbsp((b as i64 + pay + 9) as *u8, spsLen - 1, spsdst)
507 let sps: *i64 = sys_mmap(128) as *i64
508 nx_h264_parse_sps(spsdst, spsrbsp, sps)
509 let ppspos: i64 = pay + 8 + spsLen
510 let ppsLen: i64 = (b[ppspos + 1] as i64) * 256 + (b[ppspos + 2] as i64)
511 let ppsdst: *u8 = sys_mmap(ppsLen + 16)
512 let ppsrbsp: i64 = nx_h264_unescape_rbsp((b as i64 + ppspos + 3 + 1) as *u8, ppsLen - 1, ppsdst)
513 let pps: *i64 = sys_mmap(128) as *i64
514 nx_h264_parse_pps(ppsdst, ppsrbsp, pps)
515 let W: i64 = sps[2]
516 let H: i64 = sps[3]
517 let mbW: i64 = W / 16
518 let mbH: i64 = H / 16
519 let totalMB: i64 = mbW * mbH
520
521 // reference (frame0 pre-deblock) + target (frame1 pre-deblock) luma planes
522 let rzp: *i64 = sys_mmap(16) as *i64
523 let refY: *u8 = sys_read_file("knowledge/staging/media/ref_frame0.yuv\x00" as *u8, rzp)
524 if (refY as i64) == 0 { gp(fd, "no ref_frame0.yuv\n\x00" as *u8); sys_exit(1); return 1 }
525 let tzp: *i64 = sys_mmap(16) as *i64
526 let tgtY: *u8 = sys_read_file("knowledge/staging/media/ref_frame1_nodeblock.yuv\x00" as *u8, tzp)
527 if (tgtY as i64) == 0 { gp(fd, "no ref_frame1_nodeblock.yuv\n\x00" as *u8); sys_exit(1); return 1 }
528 let myY: *u8 = sys_mmap(W * H + 16)
529 var zz: i64 = 0
530 while zz < W * H { myY[zz] = 0 as u8; zz = zz + 1 }
531 // chroma planes (4:2:0): U then V after the luma plane in each YUV file
532 let cW: i64 = W / 2
533 let cH: i64 = H / 2
534 let refU: *u8 = (refY as i64 + W * H) as *u8
535 let refV: *u8 = (refY as i64 + W * H + cW * cH) as *u8
536 let tgtU: *u8 = (tgtY as i64 + W * H) as *u8
537 let tgtV: *u8 = (tgtY as i64 + W * H + cW * cH) as *u8
538 let myU: *u8 = sys_mmap(cW * cH + 16)
539 let myV: *u8 = sys_mmap(cW * cH + 16)
540 zz = 0
541 while zz < cW * cH { myU[zz] = 0 as u8; myV[zz] = 0 as u8; zz = zz + 1 }
542 let cqio: i64 = pps[9]
543
544 let vi: *i64 = sys_mmap(64) as *i64
545 nx_mp4_video_info(b, len, vi)
546 let rco: *i64 = sys_mmap(16) as *i64
547 mp4_find_box(b, vi[5], vi[6], "stco\x00" as *u8, rco)
548 let s1off: i64 = mp4_be32(b, rco[0] + 12)
549 let rsz: *i64 = sys_mmap(16) as *i64
550 mp4_find_box(b, vi[5], vi[6], "stsz\x00" as *u8, rsz)
551 var samp1: i64 = mp4_be32(b, rsz[0] + 4)
552 if samp1 == 0 { samp1 = mp4_be32(b, rsz[0] + 16) }
553 let offs: *i64 = sys_mmap(256 * 8) as *i64
554 let types: *i64 = sys_mmap(256 * 8) as *i64
555 let nc: i64 = nx_nal_split_avcc(b, s1off, s1off + samp1, 4, offs, types, 256)
556 var sidx: i64 = 0 - 1
557 var i: i64 = 0
558 while i < nc { if types[i] == 1 { if sidx < 0 { sidx = i } } i = i + 1 }
559 if sidx < 0 { gp(fd, "no P-slice\n\x00" as *u8); sys_exit(1); return 1 }
560 let noff: i64 = offs[sidx]
561 let ntype: i64 = b[noff] as i64
562 let nlen: i64 = mp4_be32(b, noff - 4)
563 let sl_dst: *u8 = sys_mmap(nlen + 64)
564 let sl_rbsp: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nlen - 1, sl_dst)
565 let sh: *i64 = sys_mmap(64) as *i64
566 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
567 br_init(sbr, sl_dst, sl_rbsp)
568 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)
569 let num_ref: i64 = sh[12] + 1
570 gp(fd, " DEBLOCK deblock_idc=\x00" as *u8); gn(fd, sh[9]); gp(fd, " offA=\x00" as *u8); gn(fd, sh[10]); gp(fd, " offB=\x00" as *u8); gn(fd, sh[11]); gp(fd, "\n\x00" as *u8)
571
572 let lbW: i64 = mbW * 4
573 let lbH: i64 = mbH * 4
574 let lumaTC: *i64 = sys_mmap(lbW * lbH * 8) as *i64
575 let cbW: i64 = mbW * 2
576 let cbH: i64 = mbH * 2
577 let uTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
578 let vTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
579 var z: i64 = 0
580 while z < lbW * lbH { lumaTC[z] = 0; z = z + 1 }
581 z = 0
582 while z < cbW * cbH { uTC[z] = 0; vTC[z] = 0; z = z + 1 }
583 let gmvx: *i64 = sys_mmap(lbW * lbH * 8) as *i64
584 let gmvy: *i64 = sys_mmap(lbW * lbH * 8) as *i64
585 let gref: *i64 = sys_mmap(lbW * lbH * 8) as *i64
586 z = 0
587 while z < lbW * lbH { gmvx[z] = 0; gmvy[z] = 0; gref[z] = 0 - 2; z = z + 1 }
588 let intraMask: *i64 = sys_mmap(totalMB * 8) as *i64
589 let mbKind: *i64 = sys_mmap(totalMB * 8) as *i64
590 let mbQP: *i64 = sys_mmap(totalMB * 8) as *i64
591 z = 0
592 while z < totalMB { intraMask[z] = 0; mbKind[z] = 0 - 9; mbQP[z] = 0; z = z + 1 }
593 // intra-pred bookkeeping: decoded[]=1 once a 4x4 block is reconstructed; i4m[]= its intra mode
594 // (0..8 for I_4x4, 2 for I_16x16/PCM) or -1 for INTER blocks (not intra -> DC for mode-pred).
595 let decoded: *i64 = sys_mmap(lbW * lbH * 8) as *i64
596 let i4m: *i64 = sys_mmap(lbW * lbH * 8) as *i64
597 z = 0
598 while z < lbW * lbH { decoded[z] = 0; i4m[z] = 0 - 1; z = z + 1 }
599 let cip: i64 = pps[7]
600 let acstore: *i64 = sys_mmap(16 * 16 * 8) as *i64
601
602 let bx4: *i64 = sys_mmap(16 * 8) as *i64
603 let by4: *i64 = sys_mmap(16 * 8) as *i64
604 bx4[0]=0; by4[0]=0; bx4[1]=1; by4[1]=0; bx4[2]=0; by4[2]=1; bx4[3]=1; by4[3]=1
605 bx4[4]=2; by4[4]=0; bx4[5]=3; by4[5]=0; bx4[6]=2; by4[6]=1; bx4[7]=3; by4[7]=1
606 bx4[8]=0; by4[8]=2; bx4[9]=1; by4[9]=2; bx4[10]=0; by4[10]=3; bx4[11]=1; by4[11]=3
607 bx4[12]=2; by4[12]=2; bx4[13]=3; by4[13]=2; bx4[14]=2; by4[14]=3; bx4[15]=3; by4[15]=3
608
609 let coeff: *i64 = sys_mmap(32 * 8) as *i64
610 let mvp: *i64 = sys_mmap(16) as *i64
611 let refs: *i64 = sys_mmap(8 * 8) as *i64
612 let subs: *i64 = sys_mmap(8 * 8) as *i64
613 var qp: i64 = sh[7]
614 var ok: i64 = 1
615 var mbAddr: i64 = 0
616 while mbAddr < totalMB {
617 if ok == 0 { mbAddr = totalMB } else {
618 let skip_run: i64 = br_read_ue(sbr)
619 var s2: i64 = 0
620 while s2 < skip_run {
621 if mbAddr < totalMB {
622 let mbX: i64 = mbAddr % mbW
623 let mbY: i64 = mbAddr / mbW
624 mbKind[mbAddr] = 10
625 nx_mvg_skip_mv(gref, gmvx, gmvy, lbW, lbH, mbX, mbY, mvp)
626 nx_mvg_fill(gref, gmvx, gmvy, lbW, mbX * 4, mbY * 4, 4, 4, 0, mvp[0], mvp[1])
627 var bl: i64 = 0
628 while bl < 16 {
629 let sbx: i64 = mbX * 4 + bx4[bl]
630 let sby: i64 = mbY * 4 + by4[bl]
631 recon_inter_4x4(myY, W, refY, W, H, sbx * 4, sby * 4, mvp[0], mvp[1], coeff, qp, 0)
632 lumaTC[sby * lbW + sbx] = 0
633 decoded[sby * lbW + sbx] = 1
634 i4m[sby * lbW + sbx] = 0 - 1
635 bl = bl + 1
636 }
637 var cc: i64 = 0
638 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 }
639 // skip chroma = pure MC (no residual)
640 var sqc: i64 = qp + cqio
641 if sqc < 0 { sqc = 0 }
642 if sqc > 51 { sqc = 51 }
643 let sQPc: i64 = nx_h264_chroma_qp(sqc)
644 let zdc: *i64 = sys_mmap(8 * 8) as *i64
645 let zac: *i64 = sys_mmap(4 * 16 * 8) as *i64
646 recon_chroma_inter_mb(myU, refU, cW, cH, mbX, mbY, gmvx, gmvy, lbW, zdc, zac, 0, sQPc)
647 recon_chroma_inter_mb(myV, refV, cW, cH, mbX, mbY, gmvx, gmvy, lbW, zdc, zac, 0, sQPc)
648 mbQP[mbAddr] = qp
649 mbAddr = mbAddr + 1
650 }
651 s2 = s2 + 1
652 }
653 if mbAddr < totalMB {
654 let mbX: i64 = mbAddr % mbW
655 let mbY: i64 = mbAddr / mbW
656 let bx0: i64 = mbX * 4
657 let by0: i64 = mbY * 4
658 let mb_type: i64 = br_read_ue(sbr)
659 let kind: i64 = nx_h264_pmb_kind(mb_type)
660 if kind >= 0 {
661 // ---- INTER ----
662 mbKind[mbAddr] = kind
663 if nx_h264_pmb_is_8x8(kind) == 1 {
664 var si: i64 = 0
665 while si < 4 { subs[si] = br_read_ue(sbr); si = si + 1 }
666 si = 0
667 while si < 4 { refs[si] = 0; si = si + 1 }
668 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 {
669 si = 0
670 while si < 4 { refs[si] = read_ref(sbr, num_ref); si = si + 1 }
671 } }
672 si = 0
673 while si < 4 {
674 let sx: i64 = bx0 + (si % 2) * 2
675 let sy: i64 = by0 + (si / 2) * 2
676 let st: i64 = subs[si]
677 var spn: i64 = nx_h264_psub_nparts(st)
678 var sp: i64 = 0
679 while sp < spn {
680 var px: i64 = sx
681 var py: i64 = sy
682 var pw: i64 = 2
683 var ph: i64 = 2
684 if st == 1 { pw = 2; ph = 1; py = sy + sp }
685 if st == 2 { pw = 1; ph = 2; px = sx + sp }
686 if st == 3 { pw = 1; ph = 1; px = sx + (sp % 2); py = sy + (sp / 2) }
687 let mvdx: i64 = br_read_se(sbr)
688 let mvdy: i64 = br_read_se(sbr)
689 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, px, py, pw, refs[si], 0, 0, mvp)
690 nx_mvg_fill(gref, gmvx, gmvy, lbW, px, py, pw, ph, refs[si], mvp[0] + mvdx, mvp[1] + mvdy)
691 sp = sp + 1
692 }
693 si = si + 1
694 }
695 }
696 if nx_h264_pmb_is_8x8(kind) == 0 {
697 let nparts: i64 = nx_h264_pmb_nparts(kind)
698 var rp: i64 = 0
699 while rp < nparts { refs[rp] = 0; rp = rp + 1 }
700 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 {
701 rp = 0
702 while rp < nparts { refs[rp] = read_ref(sbr, num_ref); rp = rp + 1 }
703 } }
704 if kind == 0 {
705 let mvdx: i64 = br_read_se(sbr)
706 let mvdy: i64 = br_read_se(sbr)
707 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 0, 0, mvp)
708 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 4, refs[0], mvp[0] + mvdx, mvp[1] + mvdy)
709 }
710 if kind == 1 {
711 let mvdx0: i64 = br_read_se(sbr)
712 let mvdy0: i64 = br_read_se(sbr)
713 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 1, 0, mvp)
714 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 2, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
715 let mvdx1: i64 = br_read_se(sbr)
716 let mvdy1: i64 = br_read_se(sbr)
717 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0 + 2, 4, refs[1], 1, 1, mvp)
718 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0 + 2, 4, 2, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
719 }
720 if kind == 2 {
721 let mvdx0: i64 = br_read_se(sbr)
722 let mvdy0: i64 = br_read_se(sbr)
723 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 2, refs[0], 2, 0, mvp)
724 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 2, 4, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
725 let mvdx1: i64 = br_read_se(sbr)
726 let mvdy1: i64 = br_read_se(sbr)
727 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0 + 2, by0, 2, refs[1], 2, 1, mvp)
728 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0 + 2, by0, 2, 4, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
729 }
730 }
731 // CBP (inter) + residual + LUMA RECON (MC from grid MV + residual)
732 let cbp: i64 = nx_h264_decode_cbp_inter(sbr)
733 let cbpL: i64 = cbp & 15
734 let cbpC: i64 = (cbp >> 4) & 3
735 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
736 var bl: i64 = 0
737 while bl < 16 {
738 let abx: i64 = bx0 + bx4[bl]
739 let aby: i64 = by0 + by4[bl]
740 let i8: i64 = bl / 4
741 let mvx: i64 = gmvx[aby * lbW + abx]
742 let mvy: i64 = gmvy[aby * lbW + abx]
743 if ((cbpL >> i8) & 1) != 0 {
744 dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff)
745 recon_inter_4x4(myY, W, refY, W, H, abx * 4, aby * 4, mvx, mvy, coeff, qp, 1)
746 }
747 if ((cbpL >> i8) & 1) == 0 {
748 lumaTC[aby * lbW + abx] = 0
749 recon_inter_4x4(myY, W, refY, W, H, abx * 4, aby * 4, mvx, mvy, coeff, qp, 0)
750 }
751 decoded[aby * lbW + abx] = 1
752 i4m[aby * lbW + abx] = 0 - 1
753 bl = bl + 1
754 }
755 let ucdc: *i64 = sys_mmap(8 * 8) as *i64
756 let vcdc: *i64 = sys_mmap(8 * 8) as *i64
757 let uac: *i64 = sys_mmap(4 * 16 * 8) as *i64
758 let vac: *i64 = sys_mmap(4 * 16 * 8) as *i64
759 var zc: i64 = 0
760 while zc < 8 { ucdc[zc] = 0; vcdc[zc] = 0; zc = zc + 1 }
761 zc = 0
762 while zc < 64 { uac[zc] = 0; vac[zc] = 0; zc = zc + 1 }
763 if cbpC != 0 {
764 nx_h264_residual_decode_cdc(sbr, ucdc)
765 nx_h264_residual_decode_cdc(sbr, vcdc)
766 if cbpC == 2 {
767 var cc: i64 = 0
768 while cc < 4 {
769 dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
770 var za: i64 = 0
771 while za < 15 { uac[cc * 16 + za] = coeff[za]; za = za + 1 }
772 cc = cc + 1
773 }
774 cc = 0
775 while cc < 4 {
776 dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
777 var za: i64 = 0
778 while za < 15 { vac[cc * 16 + za] = coeff[za]; za = za + 1 }
779 cc = cc + 1
780 }
781 }
782 }
783 if cbpC == 0 {
784 var cc: i64 = 0
785 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 }
786 }
787 var iqc: i64 = qp + cqio
788 if iqc < 0 { iqc = 0 }
789 if iqc > 51 { iqc = 51 }
790 let iQPc: i64 = nx_h264_chroma_qp(iqc)
791 recon_chroma_inter_mb(myU, refU, cW, cH, mbX, mbY, gmvx, gmvy, lbW, ucdc, uac, cbpC, iQPc)
792 recon_chroma_inter_mb(myV, refV, cW, cH, mbX, mbY, gmvx, gmvy, lbW, vcdc, vac, cbpC, iQPc)
793 }
794 if kind < 0 {
795 // ---- INTRA in P ---- decode for sync; EXCLUDE from luma compare (P-R4b-2)
796 intraMask[mbAddr] = 1
797 // mark this MB's grid blocks DECODED-INTRA (gref=-1): available to neighbours, no MV
798 var ib: i64 = 0
799 while ib < 16 {
800 let iidx: i64 = (by0 + by4[ib]) * lbW + (bx0 + bx4[ib])
801 gref[iidx] = 0 - 1; gmvx[iidx] = 0; gmvy[iidx] = 0
802 ib = ib + 1
803 }
804 let it: i64 = mb_type - 5
805 let cls: i64 = nx_h264_mb_type_class(it)
806 // chroma residual capture (filled by whichever intra cls path runs) for P-R5b recon
807 let icdcU: *i64 = sys_mmap(8 * 8) as *i64
808 let icdcV: *i64 = sys_mmap(8 * 8) as *i64
809 let iacU: *i64 = sys_mmap(4 * 16 * 8) as *i64
810 let iacV: *i64 = sys_mmap(4 * 16 * 8) as *i64
811 var zc2: i64 = 0
812 while zc2 < 8 { icdcU[zc2] = 0; icdcV[zc2] = 0; zc2 = zc2 + 1 }
813 zc2 = 0
814 while zc2 < 64 { iacU[zc2] = 0; iacV[zc2] = 0; zc2 = zc2 + 1 }
815 var iChromaMode: i64 = 0
816 var iCbpC: i64 = 0
817 if cls == 1 {
818 let der: *i64 = sys_mmap(32) as *i64
819 nx_h264_i16x16_derive(it, der)
820 let cbpL: i64 = der[2]
821 let cbpC: i64 = der[1]
822 iCbpC = cbpC
823 iChromaMode = br_read_ue(sbr)
824 let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52
825 var nA: i64 = 0
826 var avA: i64 = 0
827 if bx0 > 0 { nA = lumaTC[by0 * lbW + (bx0 - 1)]; avA = 1 }
828 var nB: i64 = 0
829 var avB: i64 = 0
830 if by0 > 0 { nB = lumaTC[(by0 - 1) * lbW + bx0]; avB = 1 }
831 let nCdc: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
832 let dcblk: *i64 = sys_mmap(16 * 8) as *i64
833 nx_h264_residual_decode(sbr, 16, nCdc, dcblk)
834 z = 0
835 while z < 256 { acstore[z] = 0; z = z + 1 }
836 var bl: i64 = 0
837 while bl < 16 {
838 let abx: i64 = bx0 + bx4[bl]
839 let aby: i64 = by0 + by4[bl]
840 let r: i64 = by4[bl] * 4 + bx4[bl]
841 i4m[aby * lbW + abx] = 2
842 if cbpL != 0 {
843 dec_luma(sbr, lumaTC, lbW, abx, aby, 15, coeff)
844 z = 0
845 while z < 15 { acstore[r * 16 + 1 + z] = coeff[z]; z = z + 1 }
846 }
847 if cbpL == 0 { lumaTC[aby * lbW + abx] = 0 }
848 decoded[aby * lbW + abx] = 1
849 bl = bl + 1
850 }
851 let dcY: *i64 = sys_mmap(16 * 8) as *i64
852 i16_dc_scale(dcblk, qp, dcY)
853 recon_i16_luma(myY, W, mbX * 16, mbY * 16, der[0], dcY, acstore, qp)
854 if cbpC != 0 {
855 nx_h264_residual_decode_cdc(sbr, icdcU)
856 nx_h264_residual_decode_cdc(sbr, icdcV)
857 if cbpC == 2 {
858 var cc: i64 = 0
859 while cc < 4 {
860 dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
861 var za: i64 = 0
862 while za < 15 { iacU[cc * 16 + za] = coeff[za]; za = za + 1 }
863 cc = cc + 1
864 }
865 cc = 0
866 while cc < 4 {
867 dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
868 var za: i64 = 0
869 while za < 15 { iacV[cc * 16 + za] = coeff[za]; za = za + 1 }
870 cc = cc + 1
871 }
872 }
873 }
874 if cbpC == 0 {
875 var cc: i64 = 0
876 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 }
877 }
878 }
879 if cls == 0 {
880 let modes: *i64 = sys_mmap(24 * 8) as *i64
881 nx_h264_parse_inxn_predmodes(sbr, modes)
882 let cbp: i64 = nx_h264_decode_cbp_intra(sbr)
883 let cbpL: i64 = cbp & 15
884 let cbpC: i64 = (cbp >> 4) & 3
885 iCbpC = cbpC
886 iChromaMode = modes[16]
887 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
888 var bl: i64 = 0
889 while bl < 16 {
890 let abx: i64 = bx0 + bx4[bl]
891 let aby: i64 = by0 + by4[bl]
892 let bpx: i64 = mbX * 16 + bx4[bl] * 4
893 let bpy: i64 = mbY * 16 + by4[bl] * 4
894 let i8: i64 = bl / 4
895 // intra4x4 mode prediction (8.3.1.1): dcPredFlag when a neighbour MB is unavailable,
896 // or (constrained_intra && inter); an inter/I16 neighbour contributes DC(2).
897 var aUnav: i64 = 1
898 if abx > 0 { if decoded[aby * lbW + (abx - 1)] == 1 { aUnav = 0 } }
899 var bUnav: i64 = 1
900 if aby > 0 { if decoded[(aby - 1) * lbW + abx] == 1 { bUnav = 0 } }
901 var dcflag: i64 = 0
902 if aUnav == 1 { dcflag = 1 }
903 if bUnav == 1 { dcflag = 1 }
904 if cip == 1 { if aUnav == 0 { if i4m[aby * lbW + (abx - 1)] < 0 { dcflag = 1 } } }
905 if cip == 1 { if bUnav == 0 { if i4m[(aby - 1) * lbW + abx] < 0 { dcflag = 1 } } }
906 var predMode: i64 = 2
907 if dcflag == 0 {
908 var mA: i64 = i4m[aby * lbW + (abx - 1)]
909 if mA < 0 { mA = 2 }
910 var mBm: i64 = i4m[(aby - 1) * lbW + abx]
911 if mBm < 0 { mBm = 2 }
912 predMode = mA
913 if mBm < mA { predMode = mBm }
914 }
915 var mode: i64 = predMode
916 if modes[bl] >= 0 {
917 let rem: i64 = modes[bl]
918 if rem < predMode { mode = rem }
919 if rem >= predMode { mode = rem + 1 }
920 }
921 i4m[aby * lbW + abx] = mode
922 z = 0
923 while z < 16 { coeff[z] = 0; z = z + 1 }
924 if ((cbpL >> i8) & 1) != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
925 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
926 // pixel-pred availability: decoded AND (constrained_intra==0 OR neighbour is intra)
927 var aT: i64 = 0
928 if aby > 0 { if decoded[(aby-1)*lbW + abx] == 1 { if cip == 0 { aT = 1 } if i4m[(aby-1)*lbW + abx] >= 0 { aT = 1 } } }
929 var aL: i64 = 0
930 if abx > 0 { if decoded[aby*lbW + (abx-1)] == 1 { if cip == 0 { aL = 1 } if i4m[aby*lbW + (abx-1)] >= 0 { aL = 1 } } }
931 var aTL: i64 = 0
932 if abx > 0 { if aby > 0 { if decoded[(aby-1)*lbW + (abx-1)] == 1 { if cip == 0 { aTL = 1 } if i4m[(aby-1)*lbW + (abx-1)] >= 0 { aTL = 1 } } } }
933 var aTR: i64 = 0
934 if aby > 0 { if abx + 1 < lbW { if decoded[(aby-1)*lbW + (abx+1)] == 1 { if cip == 0 { aTR = 1 } if i4m[(aby-1)*lbW + (abx+1)] >= 0 { aTR = 1 } } } }
935 recon_i4_block(myY, W, bpx, bpy, mode, aT, aL, aTL, aTR, coeff, qp)
936 decoded[aby * lbW + abx] = 1
937 bl = bl + 1
938 }
939 if cbpC != 0 {
940 nx_h264_residual_decode_cdc(sbr, icdcU)
941 nx_h264_residual_decode_cdc(sbr, icdcV)
942 if cbpC == 2 {
943 var cc: i64 = 0
944 while cc < 4 {
945 dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
946 var za: i64 = 0
947 while za < 15 { iacU[cc * 16 + za] = coeff[za]; za = za + 1 }
948 cc = cc + 1
949 }
950 cc = 0
951 while cc < 4 {
952 dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff)
953 var za: i64 = 0
954 while za < 15 { iacV[cc * 16 + za] = coeff[za]; za = za + 1 }
955 cc = cc + 1
956 }
957 }
958 }
959 }
960 if cls == 2 {
961 br_align(sbr)
962 let pcmpix: *i64 = sys_mmap(384 * 8) as *i64
963 var pp: i64 = 0
964 while pp < 384 { pcmpix[pp] = br_read_bits(sbr, 8); pp = pp + 1 }
965 var ry: i64 = 0
966 while ry < 16 {
967 var rx: i64 = 0
968 while rx < 16 { myY[(mbY*16 + ry) * W + (mbX*16 + rx)] = pcmpix[ry*16 + rx] as u8; rx = rx + 1 }
969 ry = ry + 1
970 }
971 ry = 0
972 while ry < 8 {
973 var rx: i64 = 0
974 while rx < 8 {
975 myU[(mbY*8 + ry) * cW + (mbX*8 + rx)] = pcmpix[256 + ry*8 + rx] as u8
976 myV[(mbY*8 + ry) * cW + (mbX*8 + rx)] = pcmpix[320 + ry*8 + rx] as u8
977 rx = rx + 1
978 }
979 ry = ry + 1
980 }
981 var bl: i64 = 0
982 while bl < 16 {
983 let abx: i64 = bx0 + bx4[bl]
984 let aby: i64 = by0 + by4[bl]
985 lumaTC[aby * lbW + abx] = 16
986 i4m[aby * lbW + abx] = 2
987 decoded[aby * lbW + abx] = 1
988 bl = bl + 1
989 }
990 var cc: i64 = 0
991 while cc < 4 { uTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 16; vTC[(mbY*2 + cc/2) * cbW + (mbX*2 + cc%2)] = 16; cc = cc + 1 }
992 }
993 if cls < 0 { ok = 0 }
994 // P-R5b: intra chroma reconstruction (cls 0/1; PCM wrote raw chroma above)
995 if cls >= 0 { if cls != 2 {
996 var aTopC: i64 = 0
997 if mbY > 0 { if cip == 0 { aTopC = 1 } if intraMask[(mbY - 1) * mbW + mbX] == 1 { aTopC = 1 } }
998 var aLeftC: i64 = 0
999 if mbX > 0 { if cip == 0 { aLeftC = 1 } if intraMask[mbY * mbW + (mbX - 1)] == 1 { aLeftC = 1 } }
1000 var iqc2: i64 = qp + cqio
1001 if iqc2 < 0 { iqc2 = 0 }
1002 if iqc2 > 51 { iqc2 = 51 }
1003 let iQPc2: i64 = nx_h264_chroma_qp(iqc2)
1004 recon_chroma_intra_mb(myU, cW, cH, mbX, mbY, iChromaMode, aTopC, aLeftC, icdcU, iacU, iCbpC, iQPc2)
1005 recon_chroma_intra_mb(myV, cW, cH, mbX, mbY, iChromaMode, aTopC, aLeftC, icdcV, iacV, iCbpC, iQPc2)
1006 } }
1007 }
1008 mbQP[mbAddr] = qp
1009 mbAddr = mbAddr + 1
1010 }
1011 }
1012 }
1013
1014 // ---- full P-frame pipeline proof: reconstruct (done) -> deblock -> compare vs ffmpeg POST-deblock ----
1015 var nIntraMB: i64 = 0
1016 var mi: i64 = 0
1017 while mi < totalMB { if intraMask[mi] == 1 { nIntraMB = nIntraMB + 1 } mi = mi + 1 }
1018 var atEnd: i64 = 0
1019 if sbr.byte_pos >= sl_rbsp - 2 { atEnd = 1 }
1020 gp(fd, " parsed MBs=\x00" as *u8); gn(fd, mbAddr); gp(fd, "/\x00" as *u8); gn(fd, totalMB)
1021 gp(fd, " reader=\x00" as *u8); gn(fd, sbr.byte_pos); gp(fd, "/\x00" as *u8); gn(fd, sl_rbsp)
1022 gp(fd, " intra_MB=\x00" as *u8); gn(fd, nIntraMB); gp(fd, "\n\x00" as *u8)
1023
1024 // ---- in-loop deblock (P boundary strengths) -> compare vs ffmpeg POST-deblock luma+chroma ----
1025 let bsHist: *i64 = sys_mmap(8 * 8) as *i64
1026 var bh: i64 = 0
1027 while bh < 5 { bsHist[bh] = 0; bh = bh + 1 }
1028 deblock_luma_p(myY, W, mbW, mbH, mbQP, gref, gmvx, gmvy, lumaTC, lbW, bsHist)
1029 gp(fd, " bS-hist: bs0=\x00" as *u8); gn(fd, bsHist[0]); gp(fd, " bs1=\x00" as *u8); gn(fd, bsHist[1]); gp(fd, " bs2=\x00" as *u8); gn(fd, bsHist[2]); gp(fd, " bs3=\x00" as *u8); gn(fd, bsHist[3]); gp(fd, " bs4=\x00" as *u8); gn(fd, bsHist[4]); gp(fd, "\n\x00" as *u8)
1030 deblock_chroma_p(myU, cW, cH, mbW, mbH, mbQP, gref, gmvx, gmvy, lumaTC, lbW, cqio)
1031 deblock_chroma_p(myV, cW, cH, mbW, mbH, mbQP, gref, gmvx, gmvy, lumaTC, lbW, cqio)
1032 let pzp: *i64 = sys_mmap(16) as *i64
1033 let postY: *u8 = sys_read_file("knowledge/staging/media/ref_frame1.yuv\x00" as *u8, pzp)
1034 let postU: *u8 = (postY as i64 + W * H) as *u8
1035 let postV: *u8 = (postY as i64 + W * H + cW * cH) as *u8
1036 var dbexact: i64 = 0
1037 var dbp: i64 = 0
1038 while dbp < W * H {
1039 if myY[dbp] == postY[dbp] { dbexact = dbexact + 1 }
1040 dbp = dbp + 1
1041 }
1042 var dbcexact: i64 = 0
1043 var dcp: i64 = 0
1044 while dcp < cW * cH {
1045 if myU[dcp] == postU[dcp] { dbcexact = dbcexact + 1 }
1046 if myV[dcp] == postV[dcp] { dbcexact = dbcexact + 1 }
1047 dcp = dcp + 1
1048 }
1049 gp(fd, " POST-DEBLOCK LUMA exact=\x00" as *u8); gn(fd, dbexact); gp(fd, "/\x00" as *u8); gn(fd, W * H); gp(fd, " diff=\x00" as *u8); gn(fd, W * H - dbexact); gp(fd, "\n\x00" as *u8)
1050 gp(fd, " POST-DEBLOCK CHROMA exact=\x00" as *u8); gn(fd, dbcexact); gp(fd, "/\x00" as *u8); gn(fd, 2 * cW * cH); gp(fd, " diff=\x00" as *u8); gn(fd, 2 * cW * cH - dbcexact); gp(fd, "\n\x00" as *u8)
1051
1052 if ok == 1 { if atEnd == 1 { if mbAddr == totalMB { if dbexact == W * H { if dbcexact == 2 * cW * cH {
1053 gp(fd, "H264-PFRAME-RECON result=ALL-PASS verdict=GREEN (FULL frame-1 POST-DEBLOCK luma+chroma bit-exact)\n\x00" as *u8)
1054 if fd > 0 { sys_close(fd) }
1055 sys_exit(0)
1056 return 0
1057 } } } } }
1058 gp(fd, "H264-PFRAME-RECON result=FAIL verdict=RED\n\x00" as *u8)
1059 if fd > 0 { sys_close(fd) }
1060 sys_exit(1)
1061 return 1
1062}