nx_h264_bframe_walk.nx source
↩ module page · 338 lines · 16779 B
1// nx_h264_bframe_walk.nx -- B-R2: ENTROPY-WALK the first B-slice of bframe_test.264, consuming every bit
2// (B mb_skip_run, B mb_types incl B_8x8 sub_mb_types, per-list L0/L1 ref_idx + mvd, inter CBP, residual,
3// intra-in-B). Proof of correct B syntax = all MBs parsed + reader lands at rbsp end (same bar as P-R1c).
4// No reconstruction yet (B-R3+). license_tier: ORIGINAL
5import "nx_syscalls.nx"
6import "nx_h264_bits.nx"
7import "nx_h264_sps.nx"
8import "nx_h264_pps.nx"
9import "nx_h264_nal.nx"
10import "nx_h264_slice.nx"
11import "nx_h264_mb.nx"
12import "nx_h264_mb_pred.nx"
13import "nx_h264_coeff_token.nx"
14import "nx_h264_cavlc_level.nx"
15import "nx_h264_residual.nx"
16import "nx_h264_nc.nx"
17import "nx_h264_bmb.nx"
18
19func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
20func gn(v: i64) -> i64 {
21 let bb: *u8 = sys_mmap(28); var m: i64 = v
22 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m }
23 let t: *u8 = sys_mmap(28); var k: i64 = 0
24 if m == 0 { t[0] = 48 as u8; k = 1 }
25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
26 var i: i64 = 0
27 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
28 sys_write(1, bb, k); return 0
29}
30func dec_luma(br: *BitReader, lumaTC: *i64, lbW: i64, bx: i64, by: i64, maxc: i64, coeff: *i64) -> i64 {
31 var nA: i64 = 0
32 var avA: i64 = 0
33 if bx > 0 { nA = lumaTC[by * lbW + (bx - 1)]; avA = 1 }
34 var nB: i64 = 0
35 var avB: i64 = 0
36 if by > 0 { nB = lumaTC[(by - 1) * lbW + bx]; avB = 1 }
37 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
38 let tc: i64 = nx_h264_residual_decode(br, maxc, nC, coeff)
39 lumaTC[by * lbW + bx] = tc
40 return tc
41}
42func dec_cac(br: *BitReader, cTC: *i64, cbW: i64, cbx: i64, cby: i64, coeff: *i64) -> i64 {
43 var nA: i64 = 0
44 var avA: i64 = 0
45 if cbx > 0 { nA = cTC[cby * cbW + (cbx - 1)]; avA = 1 }
46 var nB: i64 = 0
47 var avB: i64 = 0
48 if cby > 0 { nB = cTC[(cby - 1) * cbW + cbx]; avB = 1 }
49 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
50 let tc: i64 = nx_h264_residual_decode(br, 15, nC, coeff)
51 cTC[cby * cbW + cbx] = tc
52 return tc
53}
54func read_ref(br: *BitReader, num_ref: i64) -> i64 {
55 if num_ref == 1 { return 0 }
56 if num_ref == 2 { let bb: i64 = br_read_bit(br); return 1 - bb }
57 return br_read_ue(br)
58}
59
60func main() -> i64 {
61 let szp: *i64 = sys_mmap(16) as *i64
62 let b: *u8 = sys_read_file("knowledge/staging/media/bframe_test.264\x00" as *u8, szp)
63 if (b as i64) == 0 { gp("no bframe_test.264\n\x00" as *u8); return 1 }
64 let len: i64 = szp[0]
65 gp("B-FRAME-WALK (B-R2: B-slice entropy sync)\n\x00" as *u8)
66 let offs: *i64 = sys_mmap(512 * 8) as *i64
67 let types: *i64 = sys_mmap(512 * 8) as *i64
68 let nc: i64 = nx_nal_split_annexb(b, 0, len, offs, types, 512)
69 let sps: *i64 = sys_mmap(128) as *i64
70 let pps: *i64 = sys_mmap(128) as *i64
71 var k: i64 = 0
72 while k < nc {
73 let noff: i64 = offs[k]
74 var nend: i64 = len
75 if k + 1 < nc { nend = offs[k + 1] - 3 }
76 if types[k] == 7 { let dst: *u8 = sys_mmap(nend - noff + 16); let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst); nx_h264_parse_sps(dst, rb, sps) }
77 if types[k] == 8 { let dst: *u8 = sys_mmap(nend - noff + 16); let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst); nx_h264_parse_pps(dst, rb, pps) }
78 k = k + 1
79 }
80 let W: i64 = sps[2]
81 let H: i64 = sps[3]
82 let mbW: i64 = W / 16
83 let mbH: i64 = H / 16
84 let totalMB: i64 = mbW * mbH
85
86 // find first B-slice NAL
87 let sh: *i64 = sys_mmap(64) as *i64
88 var bk: i64 = 0 - 1
89 k = 0
90 while k < nc {
91 let isSlice: i64 = (types[k] == 1) as i64 + (types[k] == 5) as i64
92 if isSlice >= 1 { if bk < 0 {
93 let noff: i64 = offs[k]
94 let hdr: i64 = b[noff] as i64
95 var nend: i64 = len
96 if k + 1 < nc { nend = offs[k + 1] - 3 }
97 let dst: *u8 = sys_mmap(nend - noff + 16)
98 let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst)
99 let br: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
100 br_init(br, dst, rb)
101 nx_h264_parse_slice_header_br(br, hdr & 31, (hdr >> 5) & 3, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh)
102 if sh[8] == 1 { bk = k }
103 } }
104 k = k + 1
105 }
106 if bk < 0 { gp("no B-slice\n\x00" as *u8); sys_exit(1); return 1 }
107
108 let noff: i64 = offs[bk]
109 let hdr: i64 = b[noff] as i64
110 var nend: i64 = len
111 if bk + 1 < nc { nend = offs[bk + 1] - 3 }
112 let sl_dst: *u8 = sys_mmap(nend - noff + 16)
113 let sl_rbsp: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, sl_dst)
114 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
115 br_init(sbr, sl_dst, sl_rbsp)
116 nx_h264_parse_slice_header_br(sbr, hdr & 31, (hdr >> 5) & 3, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh)
117 let num_ref_l0: i64 = sh[12] + 1
118 let num_ref_l1: i64 = sh[13] + 1
119 gp(" B-slice first_mb=\x00" as *u8); gn(sh[0]); gp(" QP=\x00" as *u8); gn(sh[7]); gp(" num_ref_l0=\x00" as *u8); gn(num_ref_l0); gp(" num_ref_l1=\x00" as *u8); gn(num_ref_l1); gp(" rbsp=\x00" as *u8); gn(sl_rbsp); gp("\n\x00" as *u8)
120
121 let lbW: i64 = mbW * 4
122 let lbH: i64 = mbH * 4
123 let lumaTC: *i64 = sys_mmap(lbW * lbH * 8) as *i64
124 let cbW: i64 = mbW * 2
125 let cbH: i64 = mbH * 2
126 let uTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
127 let vTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
128 var z: i64 = 0
129 while z < lbW * lbH { lumaTC[z] = 0; z = z + 1 }
130 z = 0
131 while z < cbW * cbH { uTC[z] = 0; vTC[z] = 0; z = z + 1 }
132 let bx4: *i64 = sys_mmap(16 * 8) as *i64
133 let by4: *i64 = sys_mmap(16 * 8) as *i64
134 bx4[0]=0; by4[0]=0; bx4[1]=1; by4[1]=0; bx4[2]=0; by4[2]=1; bx4[3]=1; by4[3]=1
135 bx4[4]=2; by4[4]=0; bx4[5]=3; by4[5]=0; bx4[6]=2; by4[6]=1; bx4[7]=3; by4[7]=1
136 bx4[8]=0; by4[8]=2; bx4[9]=1; by4[9]=2; bx4[10]=0; by4[10]=3; bx4[11]=1; by4[11]=3
137 bx4[12]=2; by4[12]=2; bx4[13]=3; by4[13]=2; bx4[14]=2; by4[14]=3; bx4[15]=3; by4[15]=3
138
139 let coeff: *i64 = sys_mmap(32 * 8) as *i64
140 let subs: *i64 = sys_mmap(8 * 8) as *i64
141 var qp: i64 = sh[7]
142 var nskip: i64 = 0
143 var ndirect: i64 = 0
144 var ninter: i64 = 0
145 var nintra: i64 = 0
146 var nmvd: i64 = 0
147 var ok: i64 = 1
148 var mbAddr: i64 = 0
149 while mbAddr < totalMB {
150 if ok == 0 { mbAddr = totalMB } else {
151 let skip_run: i64 = br_read_ue(sbr)
152 var s2: i64 = 0
153 while s2 < skip_run {
154 if mbAddr < totalMB {
155 let mbX: i64 = mbAddr % mbW
156 let mbY: i64 = mbAddr / mbW
157 var bl: i64 = 0
158 while bl < 16 { lumaTC[(mbY*4 + by4[bl]) * lbW + (mbX*4 + bx4[bl])] = 0; bl = bl + 1 }
159 var cc: i64 = 0
160 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 }
161 nskip = nskip + 1
162 mbAddr = mbAddr + 1
163 }
164 s2 = s2 + 1
165 }
166 if mbAddr < totalMB {
167 let mbX: i64 = mbAddr % mbW
168 let mbY: i64 = mbAddr / mbW
169 let bx0: i64 = mbX * 4
170 let by0: i64 = mbY * 4
171 let mb_type: i64 = br_read_ue(sbr)
172 let bt: i64 = nx_h264_bmb_kind(mb_type)
173 if bt >= 0 {
174 // ---- INTER B macroblock ----
175 if nx_h264_bmb_is_direct(bt) == 1 { ndirect = ndirect + 1 }
176 if nx_h264_bmb_is_direct(bt) == 0 { ninter = ninter + 1 }
177 if nx_h264_bmb_is_8x8(bt) == 1 {
178 var si: i64 = 0
179 while si < 4 { subs[si] = br_read_ue(sbr); si = si + 1 }
180 // ref_idx L0 then L1 (per 8x8 sub-MB, if list used & not direct & num_ref>1)
181 if num_ref_l0 > 1 { si = 0; while si < 4 { if nx_h264_bsub_is_direct(subs[si]) == 0 { if nx_h264_mode_uses_l0(nx_h264_bsub_mode(subs[si])) == 1 { read_ref(sbr, num_ref_l0) } } si = si + 1 } }
182 if num_ref_l1 > 1 { si = 0; while si < 4 { if nx_h264_bsub_is_direct(subs[si]) == 0 { if nx_h264_mode_uses_l1(nx_h264_bsub_mode(subs[si])) == 1 { read_ref(sbr, num_ref_l1) } } si = si + 1 } }
183 // mvd L0 then L1 (per sub-partition)
184 si = 0
185 while si < 4 {
186 if nx_h264_bsub_is_direct(subs[si]) == 0 { if nx_h264_mode_uses_l0(nx_h264_bsub_mode(subs[si])) == 1 {
187 var sp: i64 = 0
188 let np: i64 = nx_h264_bsub_nparts(subs[si])
189 while sp < np { br_read_se(sbr); br_read_se(sbr); nmvd = nmvd + 1; sp = sp + 1 }
190 } }
191 si = si + 1
192 }
193 si = 0
194 while si < 4 {
195 if nx_h264_bsub_is_direct(subs[si]) == 0 { if nx_h264_mode_uses_l1(nx_h264_bsub_mode(subs[si])) == 1 {
196 var sp: i64 = 0
197 let np: i64 = nx_h264_bsub_nparts(subs[si])
198 while sp < np { br_read_se(sbr); br_read_se(sbr); nmvd = nmvd + 1; sp = sp + 1 }
199 } }
200 si = si + 1
201 }
202 }
203 if nx_h264_bmb_is_8x8(bt) == 0 { if nx_h264_bmb_is_direct(bt) == 0 {
204 let np: i64 = nx_h264_bmb_nparts(bt)
205 // ref_idx L0
206 if num_ref_l0 > 1 { var p: i64 = 0; while p < np { if nx_h264_mode_uses_l0(nx_h264_bmb_partmode(bt, p)) == 1 { read_ref(sbr, num_ref_l0) } p = p + 1 } }
207 if num_ref_l1 > 1 { var p: i64 = 0; while p < np { if nx_h264_mode_uses_l1(nx_h264_bmb_partmode(bt, p)) == 1 { read_ref(sbr, num_ref_l1) } p = p + 1 } }
208 // mvd L0 then L1
209 var p: i64 = 0
210 while p < np { if nx_h264_mode_uses_l0(nx_h264_bmb_partmode(bt, p)) == 1 { br_read_se(sbr); br_read_se(sbr); nmvd = nmvd + 1 } p = p + 1 }
211 p = 0
212 while p < np { if nx_h264_mode_uses_l1(nx_h264_bmb_partmode(bt, p)) == 1 { br_read_se(sbr); br_read_se(sbr); nmvd = nmvd + 1 } p = p + 1 }
213 } }
214 // CBP (inter) + residual
215 let cbp: i64 = nx_h264_decode_cbp_inter(sbr)
216 let cbpL: i64 = cbp & 15
217 let cbpC: i64 = (cbp >> 4) & 3
218 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
219 var bl: i64 = 0
220 while bl < 16 {
221 let abx: i64 = bx0 + bx4[bl]
222 let aby: i64 = by0 + by4[bl]
223 let i8: i64 = bl / 4
224 if ((cbpL >> i8) & 1) != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
225 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
226 bl = bl + 1
227 }
228 if cbpC != 0 {
229 let ucdc: *i64 = sys_mmap(8 * 8) as *i64
230 nx_h264_residual_decode_cdc(sbr, ucdc)
231 let vcdc: *i64 = sys_mmap(8 * 8) as *i64
232 nx_h264_residual_decode_cdc(sbr, vcdc)
233 if cbpC == 2 {
234 var cc: i64 = 0
235 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
236 cc = 0
237 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
238 }
239 }
240 if cbpC == 0 {
241 var cc: i64 = 0
242 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 }
243 }
244 }
245 if bt < 0 {
246 // ---- INTRA in B (mb_type-23) ----
247 nintra = nintra + 1
248 let it: i64 = mb_type - 23
249 let cls: i64 = nx_h264_mb_type_class(it)
250 if cls == 1 {
251 let der: *i64 = sys_mmap(32) as *i64
252 nx_h264_i16x16_derive(it, der)
253 let cbpL: i64 = der[2]
254 let cbpC: i64 = der[1]
255 br_read_ue(sbr)
256 let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52
257 var nA: i64 = 0
258 var avA: i64 = 0
259 if bx0 > 0 { nA = lumaTC[by0 * lbW + (bx0 - 1)]; avA = 1 }
260 var nB: i64 = 0
261 var avB: i64 = 0
262 if by0 > 0 { nB = lumaTC[(by0 - 1) * lbW + bx0]; avB = 1 }
263 let nCdc: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
264 nx_h264_residual_decode(sbr, 16, nCdc, coeff)
265 var bl: i64 = 0
266 while bl < 16 {
267 let abx: i64 = bx0 + bx4[bl]
268 let aby: i64 = by0 + by4[bl]
269 if cbpL != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 15, coeff) }
270 if cbpL == 0 { lumaTC[aby * lbW + abx] = 0 }
271 bl = bl + 1
272 }
273 if cbpC != 0 {
274 let u2: *i64 = sys_mmap(8*8) as *i64
275 nx_h264_residual_decode_cdc(sbr, u2)
276 let v2: *i64 = sys_mmap(8*8) as *i64
277 nx_h264_residual_decode_cdc(sbr, v2)
278 if cbpC == 2 {
279 var cc: i64 = 0
280 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
281 cc = 0
282 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
283 }
284 }
285 }
286 if cls == 0 {
287 let modes: *i64 = sys_mmap(24 * 8) as *i64
288 nx_h264_parse_inxn_predmodes(sbr, modes)
289 let cbp: i64 = nx_h264_decode_cbp_intra(sbr)
290 let cbpL: i64 = cbp & 15
291 let cbpC: i64 = (cbp >> 4) & 3
292 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
293 var bl: i64 = 0
294 while bl < 16 {
295 let abx: i64 = bx0 + bx4[bl]
296 let aby: i64 = by0 + by4[bl]
297 let i8: i64 = bl / 4
298 if ((cbpL >> i8) & 1) != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
299 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
300 bl = bl + 1
301 }
302 if cbpC != 0 {
303 let u3: *i64 = sys_mmap(8*8) as *i64
304 nx_h264_residual_decode_cdc(sbr, u3)
305 let v3: *i64 = sys_mmap(8*8) as *i64
306 nx_h264_residual_decode_cdc(sbr, v3)
307 if cbpC == 2 {
308 var cc: i64 = 0
309 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
310 cc = 0
311 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
312 }
313 }
314 }
315 if cls == 2 {
316 br_align(sbr)
317 var pp: i64 = 0
318 while pp < 384 { br_read_bits(sbr, 8); pp = pp + 1 }
319 }
320 if cls < 0 { ok = 0; gp(" DESYNC bad intra mb_type\n\x00" as *u8) }
321 }
322 mbAddr = mbAddr + 1
323 }
324 }
325 }
326
327 gp(" parsed MBs=\x00" as *u8); gn(mbAddr); gp("/\x00" as *u8); gn(totalMB)
328 gp(" (skip=\x00" as *u8); gn(nskip); gp(" direct=\x00" as *u8); gn(ndirect); gp(" inter=\x00" as *u8); gn(ninter); gp(" intra=\x00" as *u8); gn(nintra); gp(" mvd=\x00" as *u8); gn(nmvd); gp(")\n\x00" as *u8)
329 gp(" reader byte=\x00" as *u8); gn(sbr.byte_pos); gp("/\x00" as *u8); gn(sl_rbsp); gp(" bit=\x00" as *u8); gn(sbr.bit_pos); gp("\n\x00" as *u8)
330 if ok == 1 { if mbAddr == totalMB { if sbr.byte_pos >= sl_rbsp - 2 {
331 gp(" *** B-FRAME ENTROPY SYNC: all MBs parsed, reader at rbsp end -> B-R2 GREEN ***\n\x00" as *u8)
332 sys_exit(0)
333 return 0
334 } } }
335 gp("B-FRAME-WALK result=FAIL verdict=RED (desync)\n\x00" as *u8)
336 sys_exit(1)
337 return 1
338}