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}