code wiki / (root) / nx_h264_pframe_recon.nx

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}