code wiki / (root) / nx_h264_intra_recon.nx

nx_h264_intra_recon.nx source

↩ module page · 139 lines · 5243 B

1// nx_h264_intra_recon.nx -- H.264 INTRA luma reconstruction kernels, shared by the I-frame decoder 2// (nx_h264_decode_frame) and the P-frame decoder (intra-coded MBs inside a P-slice). Pure functions over 3// a luma plane + decoded coefficients; no entropy/bitstream state. Extracted verbatim from the proven 4// I-decoder (DRY) so intra-in-P reuses the exact, bit-exact-verified reconstruction path. 5// i16_dc_scale : inv-zigzag + Hadamard + DC level-scale of the 16 luma-DC coeffs (8.5.10). 6// recon_i16_luma : full I_16x16 luma MB (V/H/DC/Plane pred + per-4x4 AC residual + injected DC). 7// recon_i4_block : one I_4x4 luma block (9-mode pred + residual), availabilities passed by caller. 8// genealogy_id: itu_t_h264_sec8_3_intra_luma_reconstruction license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_h264_zigzag.nx" 11import "nx_h264_hadamard.nx" 12import "nx_h264_dequant.nx" 13import "nx_h264_idct.nx" 14import "nx_h264_intra16.nx" 15import "nx_h264_intra.nx" 16 17func i16_dc_scale(dcblk: *i64, qp: i64, dcY: *i64) -> i64 { 18 let dcras: *i64 = sys_mmap(16*8) as *i64 19 nx_h264_inv_zigzag4x4(dcblk, dcras) 20 nx_h264_hadamard4x4(dcras) 21 let na: *i64 = sys_mmap(8*8) as *i64 22 na[0]=10; na[1]=11; na[2]=13; na[3]=14; na[4]=16; na[5]=18 23 let ls: i64 = 16 * na[qp % 6] 24 let sh6: i64 = qp / 6 25 var qi: i64 = 0 26 while qi < 16 { 27 var v: i64 = 0 28 if qp >= 36 { v = (dcras[qi] * ls) << (sh6 - 6) } 29 if qp < 36 { v = asr(dcras[qi] * ls + (1 << (5 - sh6)), 6 - sh6) } 30 dcY[qi] = v 31 qi = qi + 1 32 } 33 return 0 34} 35 36// reconstruct a full I_16x16 luma MB at (px,py) into yf. acstore[r*16+0..15] holds the 37// AC scan block (pos0=0) per raster 4x4 block r; dcY[r] the scaled DC. predMode 0..3. 38func recon_i16_luma(yf: *u8, W: i64, px: i64, py: i64, predMode: i64, dcY: *i64, acstore: *i64, qp: i64) -> i64 { 39 let availT: i64 = 0 40 var aT: i64 = 0 41 if py > 0 { aT = 1 } 42 var aL: i64 = 0 43 if px > 0 { aL = 1 } 44 let top: *i64 = sys_mmap(16*8) as *i64 45 let left: *i64 = sys_mmap(16*8) as *i64 46 var k: i64 = 0 47 while k < 16 { 48 var tv: i64 = 0 49 if aT == 1 { tv = yf[(py-1)*W + px + k] as i64 } 50 top[k] = tv 51 var lv: i64 = 0 52 if aL == 1 { lv = yf[(py+k)*W + px - 1] as i64 } 53 left[k] = lv 54 k = k + 1 55 } 56 var tl: i64 = 0 57 if aT == 1 { if aL == 1 { tl = yf[(py-1)*W + px - 1] as i64 } } 58 let pred: *i64 = sys_mmap(256*8) as *i64 59 nx_intra16x16_pred_full(predMode, top, left, tl, aT, aL, pred) 60 let scan: *i64 = sys_mmap(16*8) as *i64 61 let dq: *i64 = sys_mmap(16*8) as *i64 62 var br: i64 = 0 63 while br < 4 { 64 var bc: i64 = 0 65 while bc < 4 { 66 let r: i64 = br * 4 + bc 67 var z: i64 = 0 68 while z < 16 { scan[z] = acstore[r*16 + z]; z = z + 1 } 69 let rast: *i64 = sys_mmap(16*8) as *i64 70 nx_h264_inv_zigzag4x4(scan, rast) 71 nx_h264_dequant4x4(rast, qp, dq) 72 dq[0] = dcY[r] 73 nx_idct4x4(dq) 74 var py4: i64 = 0 75 while py4 < 4 { 76 var px4: i64 = 0 77 while px4 < 4 { 78 var val: i64 = pred[(br*4 + py4)*16 + (bc*4 + px4)] + dq[py4*4 + px4] 79 if val < 0 { val = 0 } 80 if val > 255 { val = 255 } 81 yf[(py + br*4 + py4)*W + (px + bc*4 + px4)] = val as u8 82 px4 = px4 + 1 83 } 84 py4 = py4 + 1 85 } 86 bc = bc + 1 87 } 88 br = br + 1 89 } 90 return 0 91} 92 93// reconstruct ONE I_4x4 luma block at pixel (bpx,bpy). coeffscan = 16 scan-order levels. 94// availability flags pre-computed by caller from the decoded-block bitmap. 95func recon_i4_block(yf: *u8, W: i64, bpx: i64, bpy: i64, mode: i64, aT: i64, aL: i64, aTL: i64, aTR: i64, coeffscan: *i64, qp: i64) -> i64 { 96 let top: *i64 = sys_mmap(8*8) as *i64 97 let left: *i64 = sys_mmap(4*8) as *i64 98 var k: i64 = 0 99 while k < 4 { 100 var tv: i64 = 0 101 if aT == 1 { tv = yf[(bpy-1)*W + bpx + k] as i64 } 102 top[k] = tv 103 var lv: i64 = 0 104 if aL == 1 { lv = yf[(bpy+k)*W + bpx - 1] as i64 } 105 left[k] = lv 106 k = k + 1 107 } 108 // top-right (top[4..7]): from above-right block if available, else replicate top[3] 109 k = 0 110 while k < 4 { 111 var tv: i64 = top[3] 112 if aTR == 1 { tv = yf[(bpy-1)*W + bpx + 4 + k] as i64 } 113 if aT == 0 { tv = 0 } 114 top[4 + k] = tv 115 k = k + 1 116 } 117 var tl: i64 = 0 118 if aTL == 1 { tl = yf[(bpy-1)*W + bpx - 1] as i64 } 119 let pred: *i64 = sys_mmap(16*8) as *i64 120 nx_intra4x4_pred_full(mode, top, left, tl, aT, aL, pred) 121 let rast: *i64 = sys_mmap(16*8) as *i64 122 nx_h264_inv_zigzag4x4(coeffscan, rast) 123 let dq: *i64 = sys_mmap(16*8) as *i64 124 nx_h264_dequant4x4(rast, qp, dq) 125 nx_idct4x4(dq) 126 var yy: i64 = 0 127 while yy < 4 { 128 var xx: i64 = 0 129 while xx < 4 { 130 var val: i64 = pred[yy*4 + xx] + dq[yy*4 + xx] 131 if val < 0 { val = 0 } 132 if val > 255 { val = 255 } 133 yf[(bpy + yy)*W + (bpx + xx)] = val as u8 134 xx = xx + 1 135 } 136 yy = yy + 1 137 } 138 return 0 139}