nx_h264_mv_recon_gate.nx source
↩ module page · 451 lines · 21778 B
1// nx_h264_mv_recon_gate.nx -- P-R4a: reconstruct the per-4x4 MOTION-VECTOR FIELD of frame 1 of
2// realtest.mp4 straight from the bitstream (mvp from neighbours via the grid + mvd), then verify
3// row 0's P_L0_16x16 motion vectors BIT-EXACT against ffmpeg ground truth (12 MBs, captured by an
4// instrumented ffmpeg into knowledge/status/ffmpeg_mv_frame1.txt -- the 3rd-party oracle).
5// Walks the WHOLE P-frame (keeps entropy in sync) but asserts on the verified row-0 16x16 set.
6// Exit 0/1. Log knowledge/status/h264_mv_recon_gate.log. license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_mp4_demux.nx"
9import "nx_mp4_stbl.nx"
10import "nx_h264_bits.nx"
11import "nx_h264_sps.nx"
12import "nx_h264_pps.nx"
13import "nx_h264_nal.nx"
14import "nx_h264_slice.nx"
15import "nx_h264_mb.nx"
16import "nx_h264_mb_pred.nx"
17import "nx_h264_coeff_token.nx"
18import "nx_h264_cavlc_level.nx"
19import "nx_h264_residual.nx"
20import "nx_h264_nc.nx"
21import "nx_h264_pmb.nx"
22import "nx_h264_mvgrid.nx"
23
24func gp(fd: i64, s: *u8) -> i64 {
25 var n: i64 = 0
26 while s[n] != (0 as u8) { n = n + 1 }
27 sys_write(1, s, n); if fd > 0 { sys_write(fd, s, n) }
28 return 0
29}
30func gn(fd: i64, v: i64) -> i64 {
31 let bb: *u8 = sys_mmap(28); var m: i64 = v
32 if m < 0 { sys_write(1, "-\x00" as *u8, 1); if fd > 0 { sys_write(fd, "-\x00" as *u8, 1) } m = 0 - m }
33 let t: *u8 = sys_mmap(28); var k: i64 = 0
34 if m == 0 { t[0] = 48 as u8; k = 1 }
35 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
36 var i: i64 = 0
37 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
38 sys_write(1, bb, k); if fd > 0 { sys_write(fd, bb, k) }
39 return 0
40}
41func find_tag(b: *u8, start: i64, end: i64, s: *u8) -> i64 {
42 var i: i64 = start
43 while i + 4 <= end { if mp4_t4(b, i, s) == 1 { return i - 4 } i = i + 1 }
44 return 0 - 1
45}
46func dec_luma(br: *BitReader, lumaTC: *i64, lbW: i64, bx: i64, by: i64, maxc: i64, coeff: *i64) -> i64 {
47 var nA: i64 = 0
48 var avA: i64 = 0
49 if bx > 0 { nA = lumaTC[by * lbW + (bx - 1)]; avA = 1 }
50 var nB: i64 = 0
51 var avB: i64 = 0
52 if by > 0 { nB = lumaTC[(by - 1) * lbW + bx]; avB = 1 }
53 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
54 let tc: i64 = nx_h264_residual_decode(br, maxc, nC, coeff)
55 lumaTC[by * lbW + bx] = tc
56 return tc
57}
58func dec_cac(br: *BitReader, cTC: *i64, cbW: i64, cbx: i64, cby: i64, coeff: *i64) -> i64 {
59 var nA: i64 = 0
60 var avA: i64 = 0
61 if cbx > 0 { nA = cTC[cby * cbW + (cbx - 1)]; avA = 1 }
62 var nB: i64 = 0
63 var avB: i64 = 0
64 if cby > 0 { nB = cTC[(cby - 1) * cbW + cbx]; avB = 1 }
65 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
66 let tc: i64 = nx_h264_residual_decode(br, 15, nC, coeff)
67 cTC[cby * cbW + cbx] = tc
68 return tc
69}
70// te(v) ref_idx: num_ref==1 -> 0 (no bits); ==2 -> 1 inverted bit; >2 -> ue.
71func read_ref(sbr: *BitReader, num_ref: i64) -> i64 {
72 if num_ref == 1 { return 0 }
73 if num_ref == 2 { let bbit: i64 = br_read_bit(sbr); return 1 - bbit }
74 return br_read_ue(sbr)
75}
76
77func main() -> i64 {
78 let fd: i64 = sys_openat_append("knowledge/status/h264_mv_recon_gate.log\x00" as *u8, 0x1a4)
79 gp(fd, "H264-MV-RECON-GATE (P-R4a: frame-1 MV field, row-0 16x16 vs ffmpeg)\n\x00" as *u8)
80 let szp: *i64 = sys_mmap(16) as *i64
81 let b: *u8 = sys_read_file("knowledge/staging/media/realtest.mp4\x00" as *u8, szp)
82 if (b as i64) == 0 { gp(fd, "no realtest.mp4\n\x00" as *u8); sys_exit(1); return 1 }
83 let len: i64 = szp[0]
84 let avcc: i64 = find_tag(b, 0, len, "avcC\x00" as *u8)
85 let pay: i64 = avcc + 8
86 let spsLen: i64 = (b[pay + 6] as i64) * 256 + (b[pay + 7] as i64)
87 let spsdst: *u8 = sys_mmap(spsLen + 16)
88 let spsrbsp: i64 = nx_h264_unescape_rbsp((b as i64 + pay + 9) as *u8, spsLen - 1, spsdst)
89 let sps: *i64 = sys_mmap(128) as *i64
90 nx_h264_parse_sps(spsdst, spsrbsp, sps)
91 let ppspos: i64 = pay + 8 + spsLen
92 let ppsLen: i64 = (b[ppspos + 1] as i64) * 256 + (b[ppspos + 2] as i64)
93 let ppsdst: *u8 = sys_mmap(ppsLen + 16)
94 let ppsrbsp: i64 = nx_h264_unescape_rbsp((b as i64 + ppspos + 3 + 1) as *u8, ppsLen - 1, ppsdst)
95 let pps: *i64 = sys_mmap(128) as *i64
96 nx_h264_parse_pps(ppsdst, ppsrbsp, pps)
97 let W: i64 = sps[2]
98 let H: i64 = sps[3]
99 let mbW: i64 = W / 16
100 let mbH: i64 = H / 16
101 let totalMB: i64 = mbW * mbH
102
103 let vi: *i64 = sys_mmap(64) as *i64
104 nx_mp4_video_info(b, len, vi)
105 let rco: *i64 = sys_mmap(16) as *i64
106 mp4_find_box(b, vi[5], vi[6], "stco\x00" as *u8, rco)
107 let s1off: i64 = mp4_be32(b, rco[0] + 12)
108 let rsz: *i64 = sys_mmap(16) as *i64
109 mp4_find_box(b, vi[5], vi[6], "stsz\x00" as *u8, rsz)
110 var samp1: i64 = mp4_be32(b, rsz[0] + 4)
111 if samp1 == 0 { samp1 = mp4_be32(b, rsz[0] + 16) }
112 let offs: *i64 = sys_mmap(256 * 8) as *i64
113 let types: *i64 = sys_mmap(256 * 8) as *i64
114 let nc: i64 = nx_nal_split_avcc(b, s1off, s1off + samp1, 4, offs, types, 256)
115 var sidx: i64 = 0 - 1
116 var i: i64 = 0
117 while i < nc { if types[i] == 1 { if sidx < 0 { sidx = i } } i = i + 1 }
118 if sidx < 0 { gp(fd, "no P-slice\n\x00" as *u8); sys_exit(1); return 1 }
119 let noff: i64 = offs[sidx]
120 let ntype: i64 = b[noff] as i64
121 let nlen: i64 = mp4_be32(b, noff - 4)
122 let sl_dst: *u8 = sys_mmap(nlen + 64)
123 let sl_rbsp: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nlen - 1, sl_dst)
124 let sh: *i64 = sys_mmap(64) as *i64
125 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
126 br_init(sbr, sl_dst, sl_rbsp)
127 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)
128 let num_ref: i64 = sh[12] + 1
129 gp(fd, " P-slice QP=\x00" as *u8); gn(fd, sh[7]); gp(fd, " num_ref=\x00" as *u8); gn(fd, num_ref); gp(fd, "\n\x00" as *u8)
130
131 // residual nC maps
132 let lbW: i64 = mbW * 4
133 let lbH: i64 = mbH * 4
134 let lumaTC: *i64 = sys_mmap(lbW * lbH * 8) as *i64
135 let cbW: i64 = mbW * 2
136 let cbH: i64 = mbH * 2
137 let uTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
138 let vTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
139 var z: i64 = 0
140 while z < lbW * lbH { lumaTC[z] = 0; z = z + 1 }
141 z = 0
142 while z < cbW * cbH { uTC[z] = 0; vTC[z] = 0; z = z + 1 }
143 // MV grid (per-4x4): gref init -1 (unavailable/intra)
144 let gmvx: *i64 = sys_mmap(lbW * lbH * 8) as *i64
145 let gmvy: *i64 = sys_mmap(lbW * lbH * 8) as *i64
146 let gref: *i64 = sys_mmap(lbW * lbH * 8) as *i64
147 z = 0
148 while z < lbW * lbH { gmvx[z] = 0; gmvy[z] = 0; gref[z] = 0 - 2; z = z + 1 }
149
150 let bx4: *i64 = sys_mmap(16 * 8) as *i64
151 let by4: *i64 = sys_mmap(16 * 8) as *i64
152 bx4[0]=0; by4[0]=0; bx4[1]=1; by4[1]=0; bx4[2]=0; by4[2]=1; bx4[3]=1; by4[3]=1
153 bx4[4]=2; by4[4]=0; bx4[5]=3; by4[5]=0; bx4[6]=2; by4[6]=1; bx4[7]=3; by4[7]=1
154 bx4[8]=0; by4[8]=2; bx4[9]=1; by4[9]=2; bx4[10]=0; by4[10]=3; bx4[11]=1; by4[11]=3
155 bx4[12]=2; by4[12]=2; bx4[13]=3; by4[13]=2; bx4[14]=2; by4[14]=3; bx4[15]=3; by4[15]=3
156
157 // row-0 captured MVs (indexed by mbX)
158 let gotmx: *i64 = sys_mmap(mbW * 8) as *i64
159 let gotmy: *i64 = sys_mmap(mbW * 8) as *i64
160 let gotok: *i64 = sys_mmap(mbW * 8) as *i64
161 z = 0
162 while z < mbW { gotok[z] = 0; z = z + 1 }
163
164 let coeff: *i64 = sys_mmap(32 * 8) as *i64
165 let mvp: *i64 = sys_mmap(16) as *i64
166 let refs: *i64 = sys_mmap(8 * 8) as *i64
167 let subs: *i64 = sys_mmap(8 * 8) as *i64
168 var qp: i64 = sh[7]
169 var ok: i64 = 1
170 var nskip: i64 = 0
171 var ninter: i64 = 0
172 var nintra: i64 = 0
173 var nmvd: i64 = 0
174 var mbAddr: i64 = 0
175 while mbAddr < totalMB {
176 if ok == 0 { mbAddr = totalMB } else {
177 let skip_run: i64 = br_read_ue(sbr)
178 var s2: i64 = 0
179 while s2 < skip_run {
180 if mbAddr < totalMB {
181 let mbX: i64 = mbAddr % mbW
182 let mbY: i64 = mbAddr / mbW
183 // P_Skip: derive MV, fill grid (ref 0), residual all 0
184 nx_mvg_skip_mv(gref, gmvx, gmvy, lbW, lbH, mbX, mbY, mvp)
185 nx_mvg_fill(gref, gmvx, gmvy, lbW, mbX * 4, mbY * 4, 4, 4, 0, mvp[0], mvp[1])
186 nskip = nskip + 1
187 var bl: i64 = 0
188 while bl < 16 { lumaTC[(mbY*4 + by4[bl]) * lbW + (mbX*4 + bx4[bl])] = 0; bl = bl + 1 }
189 var cc: i64 = 0
190 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 }
191 mbAddr = mbAddr + 1
192 }
193 s2 = s2 + 1
194 }
195 if mbAddr < totalMB {
196 let mbX: i64 = mbAddr % mbW
197 let mbY: i64 = mbAddr / mbW
198 let bx0: i64 = mbX * 4
199 let by0: i64 = mbY * 4
200 let mb_type: i64 = br_read_ue(sbr)
201 let kind: i64 = nx_h264_pmb_kind(mb_type)
202 if kind >= 0 {
203 // ---- INTER ----
204 ninter = ninter + 1
205 if nx_h264_pmb_is_8x8(kind) == 1 {
206 // P_8x8 / P_8x8ref0: 4 sub_mb_types, then refs (none if ref0), then mvds per sub-partition
207 var si: i64 = 0
208 while si < 4 { subs[si] = br_read_ue(sbr); si = si + 1 }
209 si = 0
210 while si < 4 { refs[si] = 0; si = si + 1 }
211 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 {
212 si = 0
213 while si < 4 { refs[si] = read_ref(sbr, num_ref); si = si + 1 }
214 } }
215 si = 0
216 while si < 4 {
217 let sx: i64 = bx0 + (si % 2) * 2
218 let sy: i64 = by0 + (si / 2) * 2
219 let st: i64 = subs[si]
220 // sub-partition geometry: 0=8x8(1),1=8x4(2),2=4x8(2),3=4x4(4)
221 var spn: i64 = nx_h264_psub_nparts(st)
222 var sp: i64 = 0
223 while sp < spn {
224 var px: i64 = sx
225 var py: i64 = sy
226 var pw: i64 = 2
227 var ph: i64 = 2
228 if st == 1 { pw = 2; ph = 1; py = sy + sp }
229 if st == 2 { pw = 1; ph = 2; px = sx + sp }
230 if st == 3 { pw = 1; ph = 1; px = sx + (sp % 2); py = sy + (sp / 2) }
231 let mvdx: i64 = br_read_se(sbr)
232 let mvdy: i64 = br_read_se(sbr)
233 nmvd = nmvd + 1
234 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, px, py, pw, refs[si], 0, 0, mvp)
235 nx_mvg_fill(gref, gmvx, gmvy, lbW, px, py, pw, ph, refs[si], mvp[0] + mvdx, mvp[1] + mvdy)
236 sp = sp + 1
237 }
238 si = si + 1
239 }
240 }
241 if nx_h264_pmb_is_8x8(kind) == 0 {
242 let nparts: i64 = nx_h264_pmb_nparts(kind)
243 var rp: i64 = 0
244 while rp < nparts { refs[rp] = 0; rp = rp + 1 }
245 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 {
246 rp = 0
247 while rp < nparts { refs[rp] = read_ref(sbr, num_ref); rp = rp + 1 }
248 } }
249 if kind == 0 {
250 // P_L0_16x16
251 let mvdx: i64 = br_read_se(sbr)
252 let mvdy: i64 = br_read_se(sbr)
253 nmvd = nmvd + 1
254 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 0, 0, mvp)
255 let mvx: i64 = mvp[0] + mvdx
256 let mvy: i64 = mvp[1] + mvdy
257 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 4, refs[0], mvx, mvy)
258 if mbY == 0 { gotmx[mbX] = mvx; gotmy[mbX] = mvy; gotok[mbX] = 1 }
259 }
260 if kind == 1 {
261 // P_L0_16x8: top then bottom
262 let mvdx0: i64 = br_read_se(sbr)
263 let mvdy0: i64 = br_read_se(sbr)
264 nmvd = nmvd + 1
265 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 1, 0, mvp)
266 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 2, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
267 let mvdx1: i64 = br_read_se(sbr)
268 let mvdy1: i64 = br_read_se(sbr)
269 nmvd = nmvd + 1
270 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0 + 2, 4, refs[1], 1, 1, mvp)
271 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0 + 2, 4, 2, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
272 }
273 if kind == 2 {
274 // P_L0_8x16: left then right
275 let mvdx0: i64 = br_read_se(sbr)
276 let mvdy0: i64 = br_read_se(sbr)
277 nmvd = nmvd + 1
278 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 2, refs[0], 2, 0, mvp)
279 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 2, 4, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
280 let mvdx1: i64 = br_read_se(sbr)
281 let mvdy1: i64 = br_read_se(sbr)
282 nmvd = nmvd + 1
283 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0 + 2, by0, 2, refs[1], 2, 1, mvp)
284 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0 + 2, by0, 2, 4, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
285 }
286 }
287 // CBP (inter) + residual
288 let cbp: i64 = nx_h264_decode_cbp_inter(sbr)
289 let cbpL: i64 = cbp & 15
290 let cbpC: i64 = (cbp >> 4) & 3
291 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
292 var bl: i64 = 0
293 while bl < 16 {
294 let abx: i64 = bx0 + bx4[bl]
295 let aby: i64 = by0 + by4[bl]
296 let i8: i64 = bl / 4
297 if ((cbpL >> i8) & 1) != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
298 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
299 bl = bl + 1
300 }
301 if cbpC != 0 {
302 let ucdc: *i64 = sys_mmap(8 * 8) as *i64
303 nx_h264_residual_decode_cdc(sbr, ucdc)
304 let vcdc: *i64 = sys_mmap(8 * 8) as *i64
305 nx_h264_residual_decode_cdc(sbr, vcdc)
306 if cbpC == 2 {
307 var cc: i64 = 0
308 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
309 cc = 0
310 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
311 }
312 }
313 if cbpC == 0 {
314 var cc: i64 = 0
315 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 }
316 }
317 }
318 if kind < 0 {
319 // ---- INTRA in P (mb_type-5) ---- grid blocks stay ref=-1 (intra)
320 nintra = nintra + 1
321 let it: i64 = mb_type - 5
322 let cls: i64 = nx_h264_mb_type_class(it)
323 if cls == 1 {
324 let der: *i64 = sys_mmap(32) as *i64
325 nx_h264_i16x16_derive(it, der)
326 let cbpL: i64 = der[2]
327 let cbpC: i64 = der[1]
328 br_read_ue(sbr)
329 let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52
330 var nA: i64 = 0
331 var avA: i64 = 0
332 if bx0 > 0 { nA = lumaTC[by0 * lbW + (bx0 - 1)]; avA = 1 }
333 var nB: i64 = 0
334 var avB: i64 = 0
335 if by0 > 0 { nB = lumaTC[(by0 - 1) * lbW + bx0]; avB = 1 }
336 let nCdc: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
337 nx_h264_residual_decode(sbr, 16, nCdc, coeff)
338 var bl: i64 = 0
339 while bl < 16 {
340 let abx: i64 = bx0 + bx4[bl]
341 let aby: i64 = by0 + by4[bl]
342 if cbpL != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 15, coeff) }
343 if cbpL == 0 { lumaTC[aby * lbW + abx] = 0 }
344 bl = bl + 1
345 }
346 if cbpC != 0 {
347 let u2: *i64 = sys_mmap(8*8) as *i64
348 nx_h264_residual_decode_cdc(sbr, u2)
349 let v2: *i64 = sys_mmap(8*8) as *i64
350 nx_h264_residual_decode_cdc(sbr, v2)
351 if cbpC == 2 {
352 var cc: i64 = 0
353 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
354 cc = 0
355 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
356 }
357 }
358 }
359 if cls == 0 {
360 let modes: *i64 = sys_mmap(24 * 8) as *i64
361 nx_h264_parse_inxn_predmodes(sbr, modes)
362 let cbp: i64 = nx_h264_decode_cbp_intra(sbr)
363 let cbpL: i64 = cbp & 15
364 let cbpC: i64 = (cbp >> 4) & 3
365 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
366 var bl: i64 = 0
367 while bl < 16 {
368 let abx: i64 = bx0 + bx4[bl]
369 let aby: i64 = by0 + by4[bl]
370 let i8: i64 = bl / 4
371 if ((cbpL >> i8) & 1) != 0 { dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
372 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
373 bl = bl + 1
374 }
375 if cbpC != 0 {
376 let u3: *i64 = sys_mmap(8*8) as *i64
377 nx_h264_residual_decode_cdc(sbr, u3)
378 let v3: *i64 = sys_mmap(8*8) as *i64
379 nx_h264_residual_decode_cdc(sbr, v3)
380 if cbpC == 2 {
381 var cc: i64 = 0
382 while cc < 4 { dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
383 cc = 0
384 while cc < 4 { dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
385 }
386 }
387 }
388 if cls == 2 {
389 br_align(sbr)
390 var pp: i64 = 0
391 while pp < 384 { br_read_bits(sbr, 8); pp = pp + 1 }
392 }
393 if cls < 0 { ok = 0 }
394 }
395 mbAddr = mbAddr + 1
396 }
397 }
398 }
399
400 // ---- verify row-0 P_16x16 vs ffmpeg ground truth ----
401 let emx: *i64 = sys_mmap(mbW * 8) as *i64
402 let emy: *i64 = sys_mmap(mbW * 8) as *i64
403 let ehv: *i64 = sys_mmap(mbW * 8) as *i64
404 z = 0
405 while z < mbW { ehv[z] = 0; z = z + 1 }
406 emx[5]=2; emy[5]=0; ehv[5]=1
407 emx[6]=2; emy[6]=0; ehv[6]=1
408 emx[7]=3; emy[7]=0; ehv[7]=1
409 emx[8]=3; emy[8]=1; ehv[8]=1
410 emx[9]=3; emy[9]=1; ehv[9]=1
411 emx[10]=1; emy[10]=2; ehv[10]=1
412 emx[11]=1; emy[11]=2; ehv[11]=1
413 emx[12]=2; emy[12]=2; ehv[12]=1
414 emx[13]=2; emy[13]=2; ehv[13]=1
415 emx[14]=2; emy[14]=3; ehv[14]=1
416 emx[15]=2; emy[15]=0-32; ehv[15]=1
417 emx[16]=2; emy[16]=0-32; ehv[16]=1
418
419 var matched: i64 = 0
420 var checked: i64 = 0
421 var mx: i64 = 0
422 while mx < mbW {
423 if ehv[mx] == 1 {
424 checked = checked + 1
425 gp(fd, " mb(\x00" as *u8); gn(fd, mx); gp(fd, ",0) mine=(\x00" as *u8)
426 if gotok[mx] == 1 { gn(fd, gotmx[mx]); gp(fd, ",\x00" as *u8); gn(fd, gotmy[mx]) }
427 if gotok[mx] == 0 { gp(fd, "MISS\x00" as *u8) }
428 gp(fd, ") ff=(\x00" as *u8); gn(fd, emx[mx]); gp(fd, ",\x00" as *u8); gn(fd, emy[mx]); gp(fd, ")\x00" as *u8)
429 if gotok[mx] == 1 { if gotmx[mx] == emx[mx] { if gotmy[mx] == emy[mx] { matched = matched + 1; gp(fd, " OK\x00" as *u8) } } }
430 gp(fd, "\n\x00" as *u8)
431 }
432 mx = mx + 1
433 }
434 gp(fd, " counts skip=\x00" as *u8); gn(fd, nskip); gp(fd, " inter=\x00" as *u8); gn(fd, ninter); gp(fd, " intra=\x00" as *u8); gn(fd, nintra); gp(fd, " mvd_pairs=\x00" as *u8); gn(fd, nmvd); gp(fd, " (expect 1465/660/179/786)\n\x00" as *u8)
435 gp(fd, " parsed all MBs=\x00" as *u8); gn(fd, mbAddr); gp(fd, "/\x00" as *u8); gn(fd, totalMB)
436 gp(fd, " reader=\x00" as *u8); gn(fd, sbr.byte_pos); gp(fd, "/\x00" as *u8); gn(fd, sl_rbsp); gp(fd, "\n\x00" as *u8)
437 gp(fd, " row-0 16x16 MV matched=\x00" as *u8); gn(fd, matched); gp(fd, "/\x00" as *u8); gn(fd, checked); gp(fd, "\n\x00" as *u8)
438 var atEnd: i64 = 0
439 if sbr.byte_pos >= sl_rbsp - 2 { atEnd = 1 }
440
441 if ok == 1 { if atEnd == 1 { if mbAddr == totalMB { if matched == checked { if checked == 12 {
442 gp(fd, "H264-MV-RECON-GATE result=ALL-PASS verdict=GREEN\n\x00" as *u8)
443 if fd > 0 { sys_close(fd) }
444 sys_exit(0)
445 return 0
446 } } } } }
447 gp(fd, "H264-MV-RECON-GATE result=FAIL verdict=RED\n\x00" as *u8)
448 if fd > 0 { sys_close(fd) }
449 sys_exit(1)
450 return 1
451}