nx_h264_colmv_gate.nx source
↩ module page · 125 lines · 5705 B
1// nx_h264_colmv_gate.nx -- verify the co-located MV-field decoder: decode the future-anchor P-slice
2// (POC 6 = RefPicList1[0] of the first B-slice) of bframe_test.264 via nx_h264_pslice_mvfield and confirm
3// the reader lands at the rbsp end (entropy sync) + report the per-4x4 MV field stats. Exit 0/1.
4import "nx_syscalls.nx"
5import "nx_h264_bits.nx"
6import "nx_h264_sps.nx"
7import "nx_h264_pps.nx"
8import "nx_h264_nal.nx"
9import "nx_h264_slice.nx"
10import "nx_h264_poc.nx"
11import "nx_h264_pmvfield.nx"
12
13func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
14func gn(v: i64) -> i64 {
15 let bb: *u8 = sys_mmap(28); var m: i64 = v
16 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m }
17 let t: *u8 = sys_mmap(28); var k: i64 = 0
18 if m == 0 { t[0] = 48 as u8; k = 1 }
19 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
20 var i: i64 = 0
21 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
22 sys_write(1, bb, k); return 0
23}
24
25func main() -> i64 {
26 let szp: *i64 = sys_mmap(16) as *i64
27 let b: *u8 = sys_read_file("knowledge/staging/media/bframe_test.264\x00" as *u8, szp)
28 if (b as i64) == 0 { gp("no bframe_test.264\n\x00" as *u8); sys_exit(1); return 1 }
29 let len: i64 = szp[0]
30 gp("COLMV-GATE (decode future-anchor POC6 MV field)\n\x00" as *u8)
31 let offs: *i64 = sys_mmap(512 * 8) as *i64
32 let types: *i64 = sys_mmap(512 * 8) as *i64
33 let nc: i64 = nx_nal_split_annexb(b, 0, len, offs, types, 512)
34 let sps: *i64 = sys_mmap(128) as *i64
35 let pps: *i64 = sys_mmap(128) as *i64
36 var k: i64 = 0
37 while k < nc {
38 let noff: i64 = offs[k]
39 var nend: i64 = len
40 if k + 1 < nc { nend = offs[k + 1] - 3 }
41 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) }
42 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) }
43 k = k + 1
44 }
45 let mbW: i64 = sps[2] / 16
46 let mbH: i64 = sps[3] / 16
47 let lbW: i64 = mbW * 4
48 let lbH: i64 = mbH * 4
49 let max_poc_lsb: i64 = 1 << sps[11]
50 let sh: *i64 = sys_mmap(64) as *i64
51 let state: *i64 = sys_mmap(16) as *i64
52 state[0] = 0; state[1] = 0
53
54 // find the slice with POC==6 (the future anchor)
55 var ak: i64 = 0 - 1
56 var aRbsp: i64 = 0
57 let aDst: *u8 = sys_mmap(1) as *u8
58 k = 0
59 while k < nc {
60 let isSlice: i64 = (types[k] == 1) as i64 + (types[k] == 5) as i64
61 if isSlice >= 1 {
62 let noff: i64 = offs[k]
63 let hdr: i64 = b[noff] as i64
64 var nend: i64 = len
65 if k + 1 < nc { nend = offs[k + 1] - 3 }
66 let dst: *u8 = sys_mmap(nend - noff + 16)
67 let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst)
68 let br: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
69 br_init(br, dst, rb)
70 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)
71 let is_idr: i64 = (hdr & 31) == 5
72 let poc: i64 = nx_h264_poc_type0(sh[5], max_poc_lsb, is_idr, (hdr >> 5) & 3, state)
73 if poc == 6 { if ak < 0 { if sh[8] == 0 { ak = k } } }
74 }
75 k = k + 1
76 }
77 if ak < 0 { gp("no POC6 P-slice\n\x00" as *u8); sys_exit(1); return 1 }
78
79 let noff: i64 = offs[ak]
80 let hdr: i64 = b[noff] as i64
81 var nend: i64 = len
82 if ak + 1 < nc { nend = offs[ak + 1] - 3 }
83 let sl_dst: *u8 = sys_mmap(nend - noff + 16)
84 let sl_rbsp: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, sl_dst)
85 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader
86 br_init(sbr, sl_dst, sl_rbsp)
87 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)
88 let num_ref: i64 = sh[12] + 1
89
90 let gref: *i64 = sys_mmap(lbW * lbH * 8) as *i64
91 let gmvx: *i64 = sys_mmap(lbW * lbH * 8) as *i64
92 let gmvy: *i64 = sys_mmap(lbW * lbH * 8) as *i64
93 var z: i64 = 0
94 while z < lbW * lbH { gref[z] = 0 - 2; gmvx[z] = 0; gmvy[z] = 0; z = z + 1 }
95
96 let endpos: i64 = nx_h264_pslice_mvfield(sbr, sh[7], num_ref, mbW, mbH, gref, gmvx, gmvy)
97
98 // stats
99 var ninter: i64 = 0
100 var nintra: i64 = 0
101 var nundec: i64 = 0
102 var maxabs: i64 = 0
103 z = 0
104 while z < lbW * lbH {
105 if gref[z] >= 0 { ninter = ninter + 1 }
106 if gref[z] == 0 - 1 { nintra = nintra + 1 }
107 if gref[z] == 0 - 2 { nundec = nundec + 1 }
108 var ax: i64 = gmvx[z]; if ax < 0 { ax = 0 - ax }
109 var ay: i64 = gmvy[z]; if ay < 0 { ay = 0 - ay }
110 if ax > maxabs { maxabs = ax }
111 if ay > maxabs { maxabs = ay }
112 z = z + 1
113 }
114 gp(" POC6 slice QP=\x00" as *u8); gn(sh[7]); gp(" num_ref=\x00" as *u8); gn(num_ref); gp(" rbsp=\x00" as *u8); gn(sl_rbsp); gp("\n\x00" as *u8)
115 gp(" reader end=\x00" as *u8); gn(endpos); gp("/\x00" as *u8); gn(sl_rbsp); gp("\n\x00" as *u8)
116 gp(" MV field: inter4x4=\x00" as *u8); gn(ninter); gp(" intra4x4=\x00" as *u8); gn(nintra); gp(" undecoded=\x00" as *u8); gn(nundec); gp(" max|mv|=\x00" as *u8); gn(maxabs); gp("\n\x00" as *u8)
117 if endpos >= sl_rbsp - 2 { if nundec == 0 {
118 gp(" *** co-located MV field decoded, reader at rbsp end, all 4x4 covered -> GREEN ***\n\x00" as *u8)
119 sys_exit(0)
120 return 0
121 } }
122 gp("COLMV-GATE result=FAIL verdict=RED\n\x00" as *u8)
123 sys_exit(1)
124 return 1
125}