nx_h264_pmvfield.nx source
↩ module page · 243 lines · 13443 B
1// nx_h264_pmvfield.nx -- decode a P-slice's per-4x4 L0 MOTION-VECTOR FIELD (gref/gmvx/gmvy) by the proven
2// P entropy walk (skip-MV derivation, P mb_types incl 8x8 sub-partitions, mvp via the grid + mvd, residual
3// decoded only to keep entropy in sync). Used to obtain the CO-LOCATED motion of the future anchor that
4// B-slice spatial-direct prediction (8.4.1.2.2) reads. The caller pre-inits the grids to -2 (undecoded).
5// genealogy_id: itu_t_h264_pslice_mv_field license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_h264_bits.nx"
8import "nx_h264_mb.nx"
9import "nx_h264_mb_pred.nx"
10import "nx_h264_coeff_token.nx"
11import "nx_h264_cavlc_level.nx"
12import "nx_h264_residual.nx"
13import "nx_h264_nc.nx"
14import "nx_h264_pmb.nx"
15import "nx_h264_mvgrid.nx"
16
17func pmv_dec_luma(br: *BitReader, lumaTC: *i64, lbW: i64, bx: i64, by: i64, maxc: i64, coeff: *i64) -> i64 {
18 var nA: i64 = 0
19 var avA: i64 = 0
20 if bx > 0 { nA = lumaTC[by * lbW + (bx - 1)]; avA = 1 }
21 var nB: i64 = 0
22 var avB: i64 = 0
23 if by > 0 { nB = lumaTC[(by - 1) * lbW + bx]; avB = 1 }
24 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
25 let tc: i64 = nx_h264_residual_decode(br, maxc, nC, coeff)
26 lumaTC[by * lbW + bx] = tc
27 return tc
28}
29func pmv_dec_cac(br: *BitReader, cTC: *i64, cbW: i64, cbx: i64, cby: i64, coeff: *i64) -> i64 {
30 var nA: i64 = 0
31 var avA: i64 = 0
32 if cbx > 0 { nA = cTC[cby * cbW + (cbx - 1)]; avA = 1 }
33 var nB: i64 = 0
34 var avB: i64 = 0
35 if cby > 0 { nB = cTC[(cby - 1) * cbW + cbx]; avB = 1 }
36 let nC: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
37 let tc: i64 = nx_h264_residual_decode(br, 15, nC, coeff)
38 cTC[cby * cbW + cbx] = tc
39 return tc
40}
41func pmv_read_ref(sbr: *BitReader, num_ref: i64) -> i64 {
42 if num_ref == 1 { return 0 }
43 if num_ref == 2 { let bbit: i64 = br_read_bit(sbr); return 1 - bbit }
44 return br_read_ue(sbr)
45}
46
47// Walk a P-slice (sbr positioned after the slice header) filling gref/gmvx/gmvy (per-4x4, -2=undecoded
48// pre-init, -1=intra, >=0 ref). qp0 = slice QP, num_ref = num_ref_idx_l0_active. Returns reader byte_pos.
49func nx_h264_pslice_mvfield(sbr: *BitReader, qp0: i64, num_ref: i64, mbW: i64, mbH: i64,
50 gref: *i64, gmvx: *i64, gmvy: *i64) -> i64 {
51 let lbW: i64 = mbW * 4
52 let lbH: i64 = mbH * 4
53 let cbW: i64 = mbW * 2
54 let cbH: i64 = mbH * 2
55 let totalMB: i64 = mbW * mbH
56 let lumaTC: *i64 = sys_mmap(lbW * lbH * 8) as *i64
57 let uTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
58 let vTC: *i64 = sys_mmap(cbW * cbH * 8) as *i64
59 var z: i64 = 0
60 while z < lbW * lbH { lumaTC[z] = 0; z = z + 1 }
61 z = 0
62 while z < cbW * cbH { uTC[z] = 0; vTC[z] = 0; z = z + 1 }
63 let bx4: *i64 = sys_mmap(16 * 8) as *i64
64 let by4: *i64 = sys_mmap(16 * 8) as *i64
65 bx4[0]=0; by4[0]=0; bx4[1]=1; by4[1]=0; bx4[2]=0; by4[2]=1; bx4[3]=1; by4[3]=1
66 bx4[4]=2; by4[4]=0; bx4[5]=3; by4[5]=0; bx4[6]=2; by4[6]=1; bx4[7]=3; by4[7]=1
67 bx4[8]=0; by4[8]=2; bx4[9]=1; by4[9]=2; bx4[10]=0; by4[10]=3; bx4[11]=1; by4[11]=3
68 bx4[12]=2; by4[12]=2; bx4[13]=3; by4[13]=2; bx4[14]=2; by4[14]=3; bx4[15]=3; by4[15]=3
69 let coeff: *i64 = sys_mmap(32 * 8) as *i64
70 let mvp: *i64 = sys_mmap(16) as *i64
71 let refs: *i64 = sys_mmap(8 * 8) as *i64
72 let subs: *i64 = sys_mmap(8 * 8) as *i64
73 var qp: i64 = qp0
74 var ok: i64 = 1
75 var mbAddr: i64 = 0
76 while mbAddr < totalMB {
77 if ok == 0 { mbAddr = totalMB } else {
78 let skip_run: i64 = br_read_ue(sbr)
79 var s2: i64 = 0
80 while s2 < skip_run {
81 if mbAddr < totalMB {
82 let mbX: i64 = mbAddr % mbW
83 let mbY: i64 = mbAddr / mbW
84 nx_mvg_skip_mv(gref, gmvx, gmvy, lbW, lbH, mbX, mbY, mvp)
85 nx_mvg_fill(gref, gmvx, gmvy, lbW, mbX * 4, mbY * 4, 4, 4, 0, mvp[0], mvp[1])
86 var bl: i64 = 0
87 while bl < 16 { lumaTC[(mbY*4 + by4[bl]) * lbW + (mbX*4 + bx4[bl])] = 0; bl = bl + 1 }
88 var cc: i64 = 0
89 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 }
90 mbAddr = mbAddr + 1
91 }
92 s2 = s2 + 1
93 }
94 if mbAddr < totalMB {
95 let mbX: i64 = mbAddr % mbW
96 let mbY: i64 = mbAddr / mbW
97 let bx0: i64 = mbX * 4
98 let by0: i64 = mbY * 4
99 let mb_type: i64 = br_read_ue(sbr)
100 let kind: i64 = nx_h264_pmb_kind(mb_type)
101 if kind >= 0 {
102 if nx_h264_pmb_is_8x8(kind) == 1 {
103 var si: i64 = 0
104 while si < 4 { subs[si] = br_read_ue(sbr); si = si + 1 }
105 si = 0
106 while si < 4 { refs[si] = 0; si = si + 1 }
107 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 { si = 0; while si < 4 { refs[si] = pmv_read_ref(sbr, num_ref); si = si + 1 } } }
108 si = 0
109 while si < 4 {
110 let sx: i64 = bx0 + (si % 2) * 2
111 let sy: i64 = by0 + (si / 2) * 2
112 let st: i64 = subs[si]
113 var spn: i64 = nx_h264_psub_nparts(st)
114 var sp: i64 = 0
115 while sp < spn {
116 var px: i64 = sx
117 var py: i64 = sy
118 var pw: i64 = 2
119 var ph: i64 = 2
120 if st == 1 { pw = 2; ph = 1; py = sy + sp }
121 if st == 2 { pw = 1; ph = 2; px = sx + sp }
122 if st == 3 { pw = 1; ph = 1; px = sx + (sp % 2); py = sy + (sp / 2) }
123 let mvdx: i64 = br_read_se(sbr)
124 let mvdy: i64 = br_read_se(sbr)
125 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, px, py, pw, refs[si], 0, 0, mvp)
126 nx_mvg_fill(gref, gmvx, gmvy, lbW, px, py, pw, ph, refs[si], mvp[0] + mvdx, mvp[1] + mvdy)
127 sp = sp + 1
128 }
129 si = si + 1
130 }
131 }
132 if nx_h264_pmb_is_8x8(kind) == 0 {
133 let nparts: i64 = nx_h264_pmb_nparts(kind)
134 var rp: i64 = 0
135 while rp < nparts { refs[rp] = 0; rp = rp + 1 }
136 if num_ref > 1 { if nx_h264_pmb_codes_ref(kind) == 1 { rp = 0; while rp < nparts { refs[rp] = pmv_read_ref(sbr, num_ref); rp = rp + 1 } } }
137 if kind == 0 {
138 let mvdx: i64 = br_read_se(sbr)
139 let mvdy: i64 = br_read_se(sbr)
140 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 0, 0, mvp)
141 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 4, refs[0], mvp[0] + mvdx, mvp[1] + mvdy)
142 }
143 if kind == 1 {
144 let mvdx0: i64 = br_read_se(sbr)
145 let mvdy0: i64 = br_read_se(sbr)
146 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 4, refs[0], 1, 0, mvp)
147 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 4, 2, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
148 let mvdx1: i64 = br_read_se(sbr)
149 let mvdy1: i64 = br_read_se(sbr)
150 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0 + 2, 4, refs[1], 1, 1, mvp)
151 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0 + 2, 4, 2, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
152 }
153 if kind == 2 {
154 let mvdx0: i64 = br_read_se(sbr)
155 let mvdy0: i64 = br_read_se(sbr)
156 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0, by0, 2, refs[0], 2, 0, mvp)
157 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0, by0, 2, 4, refs[0], mvp[0] + mvdx0, mvp[1] + mvdy0)
158 let mvdx1: i64 = br_read_se(sbr)
159 let mvdy1: i64 = br_read_se(sbr)
160 nx_mvg_part_mvp(gref, gmvx, gmvy, lbW, lbH, bx0 + 2, by0, 2, refs[1], 2, 1, mvp)
161 nx_mvg_fill(gref, gmvx, gmvy, lbW, bx0 + 2, by0, 2, 4, refs[1], mvp[0] + mvdx1, mvp[1] + mvdy1)
162 }
163 }
164 let cbp: i64 = nx_h264_decode_cbp_inter(sbr)
165 let cbpL: i64 = cbp & 15
166 let cbpC: i64 = (cbp >> 4) & 3
167 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
168 var bl: i64 = 0
169 while bl < 16 {
170 let abx: i64 = bx0 + bx4[bl]
171 let aby: i64 = by0 + by4[bl]
172 let i8: i64 = bl / 4
173 if ((cbpL >> i8) & 1) != 0 { pmv_dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) }
174 if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 }
175 bl = bl + 1
176 }
177 if cbpC != 0 {
178 let ucdc: *i64 = sys_mmap(8 * 8) as *i64
179 nx_h264_residual_decode_cdc(sbr, ucdc)
180 let vcdc: *i64 = sys_mmap(8 * 8) as *i64
181 nx_h264_residual_decode_cdc(sbr, vcdc)
182 if cbpC == 2 {
183 var cc: i64 = 0
184 while cc < 4 { pmv_dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
185 cc = 0
186 while cc < 4 { pmv_dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 }
187 }
188 }
189 if cbpC == 0 { var cc: i64 = 0; 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 } }
190 }
191 if kind < 0 {
192 // intra-in-P: mark grid -1; decode for sync
193 var gb: i64 = 0
194 while gb < 16 { let ax: i64 = bx0 + bx4[gb]; let ay: i64 = by0 + by4[gb]; gref[ay*lbW+ax] = 0 - 1; gmvx[ay*lbW+ax] = 0; gmvy[ay*lbW+ax] = 0; gb = gb + 1 }
195 let it: i64 = mb_type - 5
196 let cls: i64 = nx_h264_mb_type_class(it)
197 if cls == 1 {
198 let der: *i64 = sys_mmap(32) as *i64
199 nx_h264_i16x16_derive(it, der)
200 let cbpL: i64 = der[2]
201 let cbpC: i64 = der[1]
202 br_read_ue(sbr)
203 let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52
204 var nA: i64 = 0
205 var avA: i64 = 0
206 if bx0 > 0 { nA = lumaTC[by0 * lbW + (bx0 - 1)]; avA = 1 }
207 var nB: i64 = 0
208 var avB: i64 = 0
209 if by0 > 0 { nB = lumaTC[(by0 - 1) * lbW + bx0]; avB = 1 }
210 let nCdc: i64 = nx_h264_nc_luma(nA, avA, nB, avB)
211 nx_h264_residual_decode(sbr, 16, nCdc, coeff)
212 var bl: i64 = 0
213 while bl < 16 { let abx: i64 = bx0 + bx4[bl]; let aby: i64 = by0 + by4[bl]; if cbpL != 0 { pmv_dec_luma(sbr, lumaTC, lbW, abx, aby, 15, coeff) } if cbpL == 0 { lumaTC[aby * lbW + abx] = 0 } bl = bl + 1 }
214 if cbpC != 0 {
215 let u2: *i64 = sys_mmap(8*8) as *i64; nx_h264_residual_decode_cdc(sbr, u2)
216 let v2: *i64 = sys_mmap(8*8) as *i64; nx_h264_residual_decode_cdc(sbr, v2)
217 if cbpC == 2 { var cc: i64 = 0; while cc < 4 { pmv_dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 } cc = 0; while cc < 4 { pmv_dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 } }
218 }
219 }
220 if cls == 0 {
221 let modes: *i64 = sys_mmap(24 * 8) as *i64
222 nx_h264_parse_inxn_predmodes(sbr, modes)
223 let cbp: i64 = nx_h264_decode_cbp_intra(sbr)
224 let cbpL: i64 = cbp & 15
225 let cbpC: i64 = (cbp >> 4) & 3
226 if cbp != 0 { let mqd: i64 = br_read_se(sbr); qp = (qp + mqd + 52) % 52 }
227 var bl: i64 = 0
228 while bl < 16 { let abx: i64 = bx0 + bx4[bl]; let aby: i64 = by0 + by4[bl]; let i8: i64 = bl / 4; if ((cbpL >> i8) & 1) != 0 { pmv_dec_luma(sbr, lumaTC, lbW, abx, aby, 16, coeff) } if ((cbpL >> i8) & 1) == 0 { lumaTC[aby * lbW + abx] = 0 } bl = bl + 1 }
229 if cbpC != 0 {
230 let u3: *i64 = sys_mmap(8*8) as *i64; nx_h264_residual_decode_cdc(sbr, u3)
231 let v3: *i64 = sys_mmap(8*8) as *i64; nx_h264_residual_decode_cdc(sbr, v3)
232 if cbpC == 2 { var cc: i64 = 0; while cc < 4 { pmv_dec_cac(sbr, uTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 } cc = 0; while cc < 4 { pmv_dec_cac(sbr, vTC, cbW, mbX*2 + (cc%2), mbY*2 + (cc/2), coeff); cc = cc + 1 } }
233 }
234 }
235 if cls == 2 { br_align(sbr); var pp: i64 = 0; while pp < 384 { br_read_bits(sbr, 8); pp = pp + 1 } }
236 if cls < 0 { ok = 0 }
237 }
238 mbAddr = mbAddr + 1
239 }
240 }
241 }
242 return sbr.byte_pos
243}