]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::codecs::{DecoderResult, DecoderError}; | |
2 | use nihav_core::frame::*; | |
3 | use nihav_codec_support::codecs::{MV, ZERO_MV}; | |
4 | use super::{CurrentMBInfo, I4X4_SCAN, Shareable}; | |
5 | use super::dispatch::{ThreadDispatcher, FrameDecodingStatus}; | |
6 | use super::dsp::*; | |
7 | use super::pic_ref::SimplifiedSliceRefs; | |
8 | use super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO}; | |
9 | use super::types::*; | |
10 | ||
11 | fn pred_intra(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
12 | let yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0]; | |
13 | match mb_info.mb_type { | |
14 | MBType::Intra16x16(imode, _, _) => { | |
15 | let id = if imode != 2 || (sstate.has_top && sstate.has_left) { | |
16 | imode as usize | |
17 | } else if !sstate.has_top && !sstate.has_left { | |
18 | IPRED8_DC128 | |
19 | } else if !sstate.has_left { | |
20 | IPRED8_DC_TOP | |
21 | } else { | |
22 | IPRED8_DC_LEFT | |
23 | }; | |
24 | IPRED_FUNCS16X16[id](&mut frm.data[yoff..], frm.stride[0], &sstate.top_line_y[sstate.mb_x * 16..], &sstate.left_y); | |
25 | }, | |
26 | MBType::Intra8x8 => { | |
27 | let mut ictx = IPred8Context::new(); | |
28 | for part in 0..4 { | |
29 | let x = (part & 1) * 2; | |
30 | let y = part & 2; | |
31 | let blk4 = x + y * 4; | |
32 | ||
33 | let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0]; | |
34 | let has_top = y > 0 || sstate.has_top; | |
35 | let has_left = x > 0 || sstate.has_left; | |
36 | let imode = mb_info.ipred[blk4]; | |
37 | let id = if imode != IntraPredMode::DC || (has_top && has_left) { | |
38 | let im_id: u8 = imode.into(); | |
39 | im_id as usize | |
40 | } else if !has_top && !has_left { | |
41 | IPRED4_DC128 | |
42 | } else if !has_left { | |
43 | IPRED4_DC_TOP | |
44 | } else { | |
45 | IPRED4_DC_LEFT | |
46 | }; | |
47 | let mb_idx = sstate.mb_x + sstate.mb_y * sstate.mb_w; | |
48 | let noright = (y == 2 || sstate.mb_x == sstate.mb_w - 1 || mb_idx < sstate.mb_start + sstate.mb_w) && (x == 2); | |
49 | let has_tl = (has_top && x > 0) || (has_left && y > 0) || (x == 0 && y == 0 && sstate.mb_x > 0 && mb_idx > sstate.mb_start + sstate.mb_w); | |
50 | if id != IPRED4_DC128 { | |
51 | let top = if y == 0 { | |
52 | &sstate.top_line_y[sstate.mb_x * 16 + x * 4..] | |
53 | } else { | |
54 | &frm.data[cur_yoff - frm.stride[0]..] | |
55 | }; | |
56 | let mut left_buf = [0; 9]; | |
57 | let left = if x == 0 { | |
58 | &sstate.left_y[y * 4..] | |
59 | } else { | |
60 | if has_tl { | |
61 | if y == 0 { | |
62 | left_buf[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1]; | |
63 | } else { | |
64 | left_buf[0] = frm.data[cur_yoff - 1 - frm.stride[0]]; | |
65 | } | |
66 | } | |
67 | if has_left { | |
68 | for (dst, src) in left_buf[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) { | |
69 | *dst = src[0]; | |
70 | } | |
71 | } | |
72 | &left_buf | |
73 | }; | |
74 | ictx.fill(top, left, has_top, has_top && !noright, has_left, has_tl); | |
75 | } | |
76 | IPRED_FUNCS8X8_LUMA[id](&mut frm.data[cur_yoff..], frm.stride[0], &ictx); | |
77 | if mb_info.coded[blk4] { | |
78 | add_coeffs8(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs8x8[part].coeffs); | |
79 | } | |
80 | } | |
81 | }, | |
82 | MBType::Intra4x4 => { | |
83 | for &(x,y) in I4X4_SCAN.iter() { | |
84 | let x = x as usize; | |
85 | let y = y as usize; | |
86 | let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0]; | |
87 | let has_top = y > 0 || sstate.has_top; | |
88 | let has_left = x > 0 || sstate.has_left; | |
89 | let imode = mb_info.ipred[x + y * 4]; | |
90 | let id = if imode != IntraPredMode::DC || (has_top && has_left) { | |
91 | let im_id: u8 = imode.into(); | |
92 | im_id as usize | |
93 | } else if !has_top && !has_left { | |
94 | IPRED4_DC128 | |
95 | } else if !has_left { | |
96 | IPRED4_DC_TOP | |
97 | } else { | |
98 | IPRED4_DC_LEFT | |
99 | }; | |
100 | let noright = (sstate.mb_x == sstate.mb_w - 1 || sstate.mb_x + sstate.mb_y * sstate.mb_w < sstate.mb_start + sstate.mb_w) && (x == 3); | |
101 | let tr: [u8; 4] = if y == 0 { | |
102 | let tsrc = &sstate.top_line_y[sstate.mb_x * 16 + x * 4..]; | |
103 | if has_top && !noright { | |
104 | [tsrc[4], tsrc[5], tsrc[6], tsrc[7]] | |
105 | } else if has_top { | |
106 | [tsrc[3]; 4] | |
107 | } else { | |
108 | [0; 4] | |
109 | } | |
110 | } else if (x & 1) == 0 || (x == 1 && y == 2) { | |
111 | let i = cur_yoff - frm.stride[0]; | |
112 | [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]] | |
113 | } else { | |
114 | let i = cur_yoff - frm.stride[0]; | |
115 | [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]] | |
116 | }; | |
117 | let mut top = [128; 4]; | |
118 | let mut left = [128; 9]; | |
119 | if y == 0 { | |
120 | if has_top { | |
121 | top.copy_from_slice(&sstate.top_line_y[sstate.mb_x * 16 + x * 4..][..4]); | |
122 | } | |
123 | } else { | |
124 | top.copy_from_slice(&frm.data[cur_yoff - frm.stride[0]..][..4]); | |
125 | } | |
126 | if x == 0 { | |
127 | if has_left { | |
128 | for (dst, &src) in left.iter_mut().zip(sstate.left_y[y * 4..].iter()) { | |
129 | *dst = src; | |
130 | } | |
131 | } | |
132 | } else { | |
133 | if y == 0 { | |
134 | if x == 0 { | |
135 | left[0] = sstate.left_y[y * 4]; | |
136 | } else if has_top { | |
137 | left[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1]; | |
138 | } | |
139 | } else { | |
140 | left[0] = frm.data[cur_yoff - frm.stride[0] - 1]; | |
141 | } | |
142 | for (dst, row) in left[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) { | |
143 | *dst = row[0]; | |
144 | } | |
145 | } | |
146 | IPRED_FUNCS4X4[id](&mut frm.data[cur_yoff..], frm.stride[0], &top, &left, &tr); | |
147 | if mb_info.coded[x + y * 4] { | |
148 | add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]); | |
149 | } | |
150 | } | |
151 | }, | |
152 | _ => unreachable!(), | |
153 | }; | |
154 | let id = if mb_info.chroma_ipred != 0 || (sstate.has_top && sstate.has_left) { | |
155 | mb_info.chroma_ipred as usize | |
156 | } else if !sstate.has_top && !sstate.has_left { | |
157 | IPRED8_DC128 | |
158 | } else if !sstate.has_left { | |
159 | IPRED8_DC_TOP | |
160 | } else { | |
161 | IPRED8_DC_LEFT | |
162 | }; | |
163 | for chroma in 1..3 { | |
164 | let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma]; | |
165 | let top = &sstate.top_line_c[chroma - 1][sstate.mb_x * 8..]; | |
166 | IPRED_FUNCS8X8_CHROMA[id](&mut frm.data[off..], frm.stride[chroma], top, &sstate.left_c[chroma - 1]); | |
167 | } | |
168 | } | |
169 | ||
170 | fn add_luma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
171 | let mut yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0]; | |
172 | if !mb_info.transform_size_8x8 { | |
173 | for y in 0..4 { | |
174 | for x in 0..4 { | |
175 | if mb_info.coded[x + y * 4] { | |
176 | add_coeffs(frm.data, yoff + x * 4, frm.stride[0], &mb_info.coeffs[x + y * 4]); | |
177 | } | |
178 | } | |
179 | yoff += frm.stride[0] * 4; | |
180 | } | |
181 | } else { | |
182 | for y in 0..2 { | |
183 | for x in 0..2 { | |
184 | if mb_info.coded[x * 2 + y * 2 * 4] { | |
185 | add_coeffs8(frm.data, yoff + x * 8, frm.stride[0], &mb_info.coeffs8x8[x + y * 2].coeffs); | |
186 | } | |
187 | } | |
188 | yoff += frm.stride[0] * 8; | |
189 | } | |
190 | } | |
191 | } | |
192 | ||
193 | fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
194 | for chroma in 1..3 { | |
195 | let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma]; | |
196 | for y in 0..2 { | |
197 | for x in 0..2 { | |
198 | let blk_no = 16 + (chroma - 1) * 4 + x + y * 2; | |
199 | if mb_info.coded[blk_no] || mb_info.coeffs[blk_no][0] != 0 { | |
200 | add_coeffs(frm.data, off + x * 4, frm.stride[chroma], &mb_info.coeffs[blk_no]); | |
201 | } | |
202 | } | |
203 | off += frm.stride[chroma] * 4; | |
204 | } | |
205 | } | |
206 | } | |
207 | ||
208 | fn do_p_mc(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV, ref_pic: Option<&SimpleFrame>, weight: &WeightInfo, mc_dsp: &mut H264MC) { | |
209 | if let Some(buf) = ref_pic { | |
210 | if !weight.is_weighted() { | |
211 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv); | |
212 | } else { | |
213 | let mut tmp = McBlock::new(); | |
214 | mc_dsp.mc_blocks(&mut tmp, buf, xpos, ypos, w, h, mv); | |
215 | ||
216 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
217 | let yw = if weight.luma_weighted { | |
218 | [weight.luma_weight, weight.luma_offset, weight.luma_shift as i8] | |
219 | } else { | |
220 | [1, 0, 0] | |
221 | }; | |
222 | let wmode = match w { | |
223 | 2 => 0, | |
224 | 4 => 1, | |
225 | 8 => 2, | |
226 | _ => 3, | |
227 | }; | |
228 | (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp.y, h, yw); | |
229 | ||
230 | for chroma in 0..2 { | |
231 | let cstride = frm.stride[chroma + 1]; | |
232 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
233 | let cw = if weight.chroma_weighted { | |
234 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
235 | } else { | |
236 | [1, 0, 0] | |
237 | }; | |
238 | let csrc = if chroma == 0 { &tmp.u } else { &tmp.v }; | |
239 | (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw); | |
240 | } | |
241 | } | |
242 | } else { | |
243 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
244 | } | |
245 | } | |
246 | ||
247 | #[allow(clippy::match_like_matches_macro)] | |
248 | fn do_b_mc(frm: &mut NASimpleVideoFrame<u8>, mode: BMode, xpos: usize, ypos: usize, w: usize, h: usize, mv0: MV, ref_pic0: Option<&SimpleFrame>, weight0: &WeightInfo, mv1: MV, ref_pic1: Option<&SimpleFrame>, weight1: &WeightInfo, mc_dsp: &mut H264MC) { | |
249 | let do_weight = match (mode, weight0.is_weighted(), weight1.is_weighted()) { | |
250 | (BMode::L0, true, _) => true, | |
251 | (BMode::L1, _, true) => true, | |
252 | (BMode::Bi, true, true) => true, | |
253 | _ => false, | |
254 | }; | |
255 | if !do_weight { | |
256 | match mode { | |
257 | BMode::L0 => { | |
258 | if let Some(buf) = ref_pic0 { | |
259 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv0); | |
260 | } else { | |
261 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
262 | } | |
263 | }, | |
264 | BMode::L1 => { | |
265 | if let Some(buf) = ref_pic1 { | |
266 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv1); | |
267 | } else { | |
268 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
269 | } | |
270 | }, | |
271 | BMode::Bi => { | |
272 | match (ref_pic0, ref_pic1) { | |
273 | (Some(buf0), Some(buf1)) => { | |
274 | mc_dsp.do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
275 | mc_dsp.do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1); | |
276 | }, | |
277 | (Some(buf0), None) => { | |
278 | mc_dsp.do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
279 | }, | |
280 | (None, Some(buf1)) => { | |
281 | mc_dsp.do_mc(frm, buf1, xpos, ypos, w, h, mv1); | |
282 | }, | |
283 | (None, None) => { | |
284 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
285 | }, | |
286 | }; | |
287 | }, | |
288 | }; | |
289 | } else { | |
290 | let mut tmp0 = McBlock::new(); | |
291 | let mut tmp1 = McBlock::new(); | |
292 | match (mode, ref_pic0, ref_pic1) { | |
293 | (BMode::L0, Some(buf), _) | (BMode::L1, _, Some(buf)) => { | |
294 | let (mv, weight) = if mode == BMode::L0 { (mv0, weight0) } else { (mv1, weight1) }; | |
295 | mc_dsp.mc_blocks(&mut tmp0, buf, xpos, ypos, w, h, mv); | |
296 | ||
297 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
298 | let yw = if weight.luma_weighted { | |
299 | [weight.luma_weight, weight.luma_offset, weight.luma_shift as i8] | |
300 | } else { | |
301 | [1, 0, 0] | |
302 | }; | |
303 | let wmode = match w { | |
304 | 2 => 0, | |
305 | 4 => 1, | |
306 | 8 => 2, | |
307 | _ => 3, | |
308 | }; | |
309 | (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp0.y, h, yw); | |
310 | ||
311 | for chroma in 0..2 { | |
312 | let cstride = frm.stride[chroma + 1]; | |
313 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
314 | let cw = if weight.chroma_weighted { | |
315 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
316 | } else { | |
317 | [1, 0, 0] | |
318 | }; | |
319 | let csrc = if chroma == 0 { &tmp0.u } else { &tmp0.v }; | |
320 | (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw); | |
321 | } | |
322 | }, | |
323 | (BMode::Bi, Some(buf0), Some(buf1)) => { // do both and avg | |
324 | mc_dsp.mc_blocks(&mut tmp0, buf0, xpos, ypos, w, h, mv0); | |
325 | mc_dsp.mc_blocks(&mut tmp1, buf1, xpos, ypos, w, h, mv1); | |
326 | ||
327 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
328 | let yw = match (weight0.luma_weighted, weight1.luma_weighted) { | |
329 | (true, true) => [weight0.luma_weight, weight0.luma_offset, weight1.luma_weight, weight1.luma_offset, weight0.luma_shift as i8], | |
330 | (true, false) => [weight0.luma_weight, weight0.luma_offset, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
331 | (false, true) => [1 << weight1.luma_shift, 0, weight1.luma_weight, weight1.luma_offset, weight1.luma_shift as i8], | |
332 | (false, false) => [1, 0, 1, 0, 0], | |
333 | }; | |
334 | let wmode = match w { | |
335 | 2 => 0, | |
336 | 4 => 1, | |
337 | 8 => 2, | |
338 | _ => 3, | |
339 | }; | |
340 | (mc_dsp.put_block_weighted2[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp0.y, &tmp1.y, h, yw); | |
341 | ||
342 | for chroma in 0..2 { | |
343 | let cstride = frm.stride[chroma + 1]; | |
344 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
345 | let cw0 = weight0.chroma_weight[chroma]; | |
346 | let co0 = weight0.chroma_offset[chroma]; | |
347 | let cw1 = weight1.chroma_weight[chroma]; | |
348 | let co1 = weight1.chroma_offset[chroma]; | |
349 | let cw = match (weight0.chroma_weighted, weight1.chroma_weighted) { | |
350 | (true, true) => [cw0, co0, cw1, co1, weight0.luma_shift as i8], | |
351 | (true, false) => [cw0, co0, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
352 | (false, true) => [1 << weight1.luma_shift, 0, cw1, co1, weight1.luma_shift as i8], | |
353 | (false, false) => [1, 0, 1, 0, 0], | |
354 | }; | |
355 | let csrc0 = if chroma == 0 { &tmp0.u } else { &tmp0.v }; | |
356 | let csrc1 = if chroma == 0 { &tmp1.u } else { &tmp1.v }; | |
357 | (mc_dsp.put_block_weighted2[wmode - 1])(&mut frm.data[coff..], cstride, csrc0, csrc1, h / 2, cw); | |
358 | } | |
359 | }, | |
360 | _ => { | |
361 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
362 | }, | |
363 | }; | |
364 | } | |
365 | } | |
366 | ||
367 | fn do_b_mc_4x4bi(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, mv: &[MV; 2], ref_pic0: Option<&SimpleFrame>, weight0: &WeightInfo, ref_pic1: Option<&SimpleFrame>, weight1: &WeightInfo, mc_dsp: &mut H264MC) { | |
368 | if !weight0.is_weighted() || !weight1.is_weighted() { | |
369 | match (ref_pic0, ref_pic1) { | |
370 | (Some(buf0), Some(buf1)) => { | |
371 | mc_dsp.do_mc(frm, buf0, xpos, ypos, 4, 4, mv[0]); | |
372 | mc_dsp.do_mc_avg(frm, buf1, xpos, ypos, 4, 4, mv[1]); | |
373 | }, | |
374 | (Some(buf0), None) => { | |
375 | mc_dsp.do_mc(frm, buf0, xpos, ypos, 4, 4, mv[0]); | |
376 | }, | |
377 | (None, Some(buf1)) => { | |
378 | mc_dsp.do_mc(frm, buf1, xpos, ypos, 4, 4, mv[1]); | |
379 | }, | |
380 | (None, None) => { | |
381 | mc_dsp.gray_block(frm, xpos, ypos, 4, 4); | |
382 | }, | |
383 | }; | |
384 | } else { | |
385 | let mut tmp0 = McBlock::new(); | |
386 | let mut tmp1 = McBlock::new(); | |
387 | match (ref_pic0, ref_pic1) { | |
388 | (Some(buf0), Some(buf1)) => { // do both and avg | |
389 | mc_dsp.mc_blocks(&mut tmp0, buf0, xpos, ypos, 4, 4, mv[0]); | |
390 | mc_dsp.mc_blocks(&mut tmp1, buf1, xpos, ypos, 4, 4, mv[1]); | |
391 | ||
392 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
393 | let yw = match (weight0.luma_weighted, weight1.luma_weighted) { | |
394 | (true, true) => [weight0.luma_weight, weight0.luma_offset, weight1.luma_weight, weight1.luma_offset, weight0.luma_shift as i8], | |
395 | (true, false) => [weight0.luma_weight, weight0.luma_offset, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
396 | (false, true) => [1 << weight1.luma_shift, 0, weight1.luma_weight, weight1.luma_offset, weight1.luma_shift as i8], | |
397 | (false, false) => [1, 0, 1, 0, 0], | |
398 | }; | |
399 | (mc_dsp.put_block_weighted2[1])(&mut frm.data[yoff..], frm.stride[0], &tmp0.y, &tmp1.y, 4, yw); | |
400 | ||
401 | for chroma in 0..2 { | |
402 | let cstride = frm.stride[chroma + 1]; | |
403 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
404 | let cw0 = weight0.chroma_weight[chroma]; | |
405 | let co0 = weight0.chroma_offset[chroma]; | |
406 | let cw1 = weight1.chroma_weight[chroma]; | |
407 | let co1 = weight1.chroma_offset[chroma]; | |
408 | let cw = match (weight0.chroma_weighted, weight1.chroma_weighted) { | |
409 | (true, true) => [cw0, co0, cw1, co1, weight0.luma_shift as i8], | |
410 | (true, false) => [cw0, co0, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
411 | (false, true) => [1 << weight1.luma_shift, 0, cw1, co1, weight1.luma_shift as i8], | |
412 | (false, false) => [1, 0, 1, 0, 0], | |
413 | }; | |
414 | let csrc0 = if chroma == 0 { &tmp0.u } else { &tmp0.v }; | |
415 | let csrc1 = if chroma == 0 { &tmp1.u } else { &tmp1.v }; | |
416 | (mc_dsp.put_block_weighted2[0])(&mut frm.data[coff..], cstride, csrc0, csrc1, 2, cw); | |
417 | } | |
418 | }, | |
419 | _ => { | |
420 | mc_dsp.gray_block(frm, xpos, ypos, 4, 4); | |
421 | }, | |
422 | }; | |
423 | } | |
424 | } | |
425 | ||
426 | fn get_weights(slice_hdr: &SliceHeader, frame_refs: &SimplifiedSliceRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) { | |
427 | let idx_l0 = ref_l0.index(); | |
428 | let idx_l1 = ref_l1.index(); | |
429 | if mode != BMode::Bi || weight_mode != 2 { | |
430 | (slice_hdr.get_weight(0, idx_l0), slice_hdr.get_weight(1, idx_l1)) | |
431 | } else if let (Some(Some(ref pic0)), Some(Some(ref pic1))) = (frame_refs.ref_list0.get(idx_l0), frame_refs.ref_list1.get(idx_l1)) { | |
432 | let r0_poc = pic0.full_id as u16; | |
433 | let r1_poc = pic1.full_id as u16; | |
434 | let cur_id = frame_refs.cur_id as u16; | |
435 | if (r0_poc == r1_poc) || pic0.long_term || pic1.long_term { | |
436 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
437 | } | |
438 | ||
439 | let td = (i32::from(r1_poc) - i32::from(r0_poc)).max(-128).min(127); | |
440 | let tx = (16384 + (td / 2).abs()) / td; | |
441 | let tb = (i32::from(cur_id) - i32::from(r0_poc)).max(-128).min(127); | |
442 | let scale = ((tb * tx + 32) >> 6).max(-1024).min(1023); | |
443 | if scale == 128 || (scale >> 2) < -64 || (scale >> 2) > 128 { | |
444 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
445 | } | |
446 | let w1 = (scale >> 2) as i8; | |
447 | let w0 = 64 - w1; | |
448 | ||
449 | let weight0 = WeightInfo { | |
450 | luma_weighted: true, | |
451 | luma_weight: w0, | |
452 | luma_offset: 0, | |
453 | luma_shift: 5, | |
454 | chroma_weighted: true, | |
455 | chroma_weight: [w0; 2], | |
456 | chroma_offset: [0; 2], | |
457 | chroma_shift: 5, | |
458 | }; | |
459 | let weight1 = WeightInfo { | |
460 | luma_weighted: true, | |
461 | luma_weight: w1, | |
462 | luma_offset: 0, | |
463 | luma_shift: 5, | |
464 | chroma_weighted: true, | |
465 | chroma_weight: [w1; 2], | |
466 | chroma_offset: [0; 2], | |
467 | chroma_shift: 5, | |
468 | }; | |
469 | ||
470 | (weight0, weight1) | |
471 | } else { | |
472 | (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO) | |
473 | } | |
474 | } | |
475 | ||
476 | pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &SimplifiedSliceRefs, mc_dsp: &mut H264MC, weight_mode: u8) { | |
477 | let xpos = sstate.mb_x * 16; | |
478 | let ypos = sstate.mb_y * 16; | |
479 | ||
480 | match mb_info.mb_type { | |
481 | MBType::Intra16x16(_, _, _) => { | |
482 | pred_intra(frm, sstate, mb_info); | |
483 | }, | |
484 | MBType::Intra4x4 | MBType::Intra8x8 => { | |
485 | pred_intra(frm, sstate, mb_info); | |
486 | }, | |
487 | MBType::PCM => {}, | |
488 | MBType::PSkip => { | |
489 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
490 | let rpic = frame_refs.select_ref_pic(0, 0); | |
491 | let weight = &slice_hdr.get_weight(0, 0); | |
492 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
493 | }, | |
494 | MBType::P16x16 => { | |
495 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
496 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
497 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
498 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
499 | }, | |
500 | MBType::P16x8 | MBType::P8x16 => { | |
501 | let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 { | |
502 | (16, 8, 0, 8) | |
503 | } else { | |
504 | (8, 16, 8, 0) | |
505 | }; | |
506 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
507 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
508 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
509 | do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight, mc_dsp); | |
510 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
511 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index()); | |
512 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index()); | |
513 | do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight, mc_dsp); | |
514 | }, | |
515 | MBType::P8x8 | MBType::P8x8Ref0 => { | |
516 | for part in 0..4 { | |
517 | let bx = (part & 1) * 8; | |
518 | let by = (part & 2) * 4; | |
519 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
520 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
521 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index()); | |
522 | ||
523 | match mb_info.sub_mb_type[part] { | |
524 | SubMBType::P8x8 => { | |
525 | do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight, mc_dsp); | |
526 | }, | |
527 | SubMBType::P8x4 => { | |
528 | do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic, weight, mc_dsp); | |
529 | let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0]; | |
530 | do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight, mc_dsp); | |
531 | }, | |
532 | SubMBType::P4x8 => { | |
533 | do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic, weight, mc_dsp); | |
534 | let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0]; | |
535 | do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight, mc_dsp); | |
536 | }, | |
537 | SubMBType::P4x4 => { | |
538 | for sb_no in 0..4 { | |
539 | let sxpos = xpos + bx + (sb_no & 1) * 4; | |
540 | let sypos = ypos + by + (sb_no & 2) * 2; | |
541 | let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4; | |
542 | let mv = sstate.get_cur_blk4(sblk_no).mv[0]; | |
543 | do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic, weight, mc_dsp); | |
544 | } | |
545 | }, | |
546 | _ => unreachable!(), | |
547 | }; | |
548 | } | |
549 | }, | |
550 | MBType::B16x16(mode) => { | |
551 | let mv0 = sstate.get_cur_blk4(0).mv[0]; | |
552 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
553 | let mv1 = sstate.get_cur_blk4(0).mv[1]; | |
554 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index()); | |
555 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]); | |
556 | do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
557 | }, | |
558 | MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { | |
559 | let (pw, ph) = mb_info.mb_type.size(); | |
560 | let (px, py) = (pw & 8, ph & 8); | |
561 | let modes = [mode0, mode1]; | |
562 | let (mut bx, mut by) = (0, 0); | |
563 | for part in 0..2 { | |
564 | let blk = if part == 0 { 0 } else { (px / 4) + py }; | |
565 | let mv0 = sstate.get_cur_blk4(blk).mv[0]; | |
566 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
567 | let mv1 = sstate.get_cur_blk4(blk).mv[1]; | |
568 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index()); | |
569 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]); | |
570 | do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
571 | bx += px; | |
572 | by += py; | |
573 | } | |
574 | }, | |
575 | MBType::Direct | MBType::BSkip => { | |
576 | let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type; | |
577 | let is_16x16 = colo_mb_type.is_16x16_ref(); | |
578 | ||
579 | if is_16x16 { | |
580 | let mv = sstate.get_cur_blk4(0).mv; | |
581 | let ref_idx = sstate.get_cur_blk8(0).ref_idx; | |
582 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
583 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
584 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
585 | do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
586 | } else { | |
587 | for blk4 in 0..16 { | |
588 | let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx; | |
589 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
590 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
591 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
592 | let mv = &sstate.get_cur_blk4(blk4).mv; | |
593 | do_b_mc_4x4bi(frm, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, mv, rpic0, &weight0, rpic1, &weight1, mc_dsp); | |
594 | } | |
595 | } | |
596 | sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); }); | |
597 | }, | |
598 | MBType::B8x8 => { | |
599 | for part in 0..4 { | |
600 | let ridx = sstate.get_cur_blk8(part).ref_idx; | |
601 | let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index()); | |
602 | let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index()); | |
603 | let subtype = mb_info.sub_mb_type[part]; | |
604 | let blk8 = (part & 1) * 2 + (part & 2) * 4; | |
605 | let mut bx = (part & 1) * 8; | |
606 | let mut by = (part & 2) * 4; | |
607 | match subtype { | |
608 | SubMBType::Direct8x8 => { | |
609 | for blk in 0..4 { | |
610 | let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx; | |
611 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
612 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
613 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
614 | let mv = &sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv; | |
615 | do_b_mc_4x4bi(frm, xpos + bx, ypos + by, mv, rpic0, &weight0, rpic1, &weight1, mc_dsp); | |
616 | bx += 4; | |
617 | if blk == 1 { | |
618 | bx -= 8; | |
619 | by += 4; | |
620 | } | |
621 | } | |
622 | sstate.get_cur_blk8(part).ref_idx[0].set_direct(); | |
623 | sstate.get_cur_blk8(part).ref_idx[1].set_direct(); | |
624 | }, | |
625 | SubMBType::B8x8(mode) => { | |
626 | let mv = sstate.get_cur_blk4(blk8).mv; | |
627 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
628 | do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
629 | }, | |
630 | SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => { | |
631 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
632 | let (pw, ph) = subtype.size(); | |
633 | let mv = sstate.get_cur_blk4(blk8).mv; | |
634 | do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
635 | let addr2 = blk8 + (pw & 4) / 4 + (ph & 4); | |
636 | let mv = sstate.get_cur_blk4(addr2).mv; | |
637 | do_b_mc(frm, mode, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
638 | }, | |
639 | SubMBType::B4x4(mode) => { | |
640 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
641 | for i in 0..4 { | |
642 | let addr2 = blk8 + (i & 1) + (i & 2) * 2; | |
643 | let mv = sstate.get_cur_blk4(addr2).mv; | |
644 | do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
645 | bx += 4; | |
646 | if i == 1 { | |
647 | bx -= 8; | |
648 | by += 4; | |
649 | } | |
650 | } | |
651 | }, | |
652 | _ => unreachable!(), | |
653 | }; | |
654 | } | |
655 | }, | |
656 | }; | |
657 | if !mb_info.mb_type.is_skip() { | |
658 | if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 { | |
659 | add_luma(frm, sstate, mb_info); | |
660 | } | |
661 | add_chroma(frm, sstate, mb_info); | |
662 | } | |
663 | } | |
664 | ||
665 | pub fn wait_for_mb(disp: &Shareable<ThreadDispatcher>, sstate: &SliceState, xpos: usize, ypos: usize, mv: MV, ref_id: u32) -> DecoderResult<()> { | |
666 | let xpos = xpos as isize + ((mv.x >> 2) as isize) + 4; | |
667 | let ypos = ypos as isize + ((mv.y >> 2) as isize) + 4; | |
668 | let dst_mb_x = ((xpos.max(0) as usize) / 16).min(sstate.mb_w - 1); | |
669 | let dst_mb_y = ((ypos.max(0) as usize) / 16).min(sstate.mb_h - 1); | |
670 | let expected_mb = dst_mb_x + dst_mb_y * sstate.mb_w; | |
671 | loop { | |
672 | if let Ok(ds) = disp.read() { | |
673 | match ds.check_pos(ref_id, expected_mb) { | |
674 | FrameDecodingStatus::Ok => return Ok(()), | |
675 | FrameDecodingStatus::NotReady => {}, | |
676 | _ => return Err(DecoderError::MissingReference), | |
677 | }; | |
678 | } | |
679 | std::thread::yield_now(); | |
680 | } | |
681 | } | |
682 | ||
683 | fn wait_b_mc(disp: &Shareable<ThreadDispatcher>, sstate: &SliceState, frame_refs: &SimplifiedSliceRefs, mv: [MV; 2], ref_idx: [PicRef; 2], xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { | |
684 | if let Some(ref_id) = frame_refs.get_ref_id(0, ref_idx[0].index()) { | |
685 | wait_for_mb(disp, sstate, xpos + w, ypos + h, mv[0], ref_id)?; | |
686 | } | |
687 | if let Some(ref_id) = frame_refs.get_ref_id(1, ref_idx[1].index()) { | |
688 | wait_for_mb(disp, sstate, xpos + w, ypos + h, mv[1], ref_id)?; | |
689 | } | |
690 | Ok(()) | |
691 | } | |
692 | ||
693 | pub fn recon_mb_mt(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &SimplifiedSliceRefs, mc_dsp: &mut H264MC, weight_mode: u8, disp: &Shareable<ThreadDispatcher>) -> DecoderResult<()> { | |
694 | let xpos = sstate.mb_x * 16; | |
695 | let ypos = sstate.mb_y * 16; | |
696 | ||
697 | match mb_info.mb_type { | |
698 | MBType::Intra16x16(_, _, _) => { | |
699 | pred_intra(frm, sstate, mb_info); | |
700 | }, | |
701 | MBType::Intra4x4 | MBType::Intra8x8 => { | |
702 | pred_intra(frm, sstate, mb_info); | |
703 | }, | |
704 | MBType::PCM => {}, | |
705 | MBType::PSkip => { | |
706 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
707 | if let Some(ref_id) = frame_refs.get_ref_id(0, 0) { | |
708 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?; | |
709 | } | |
710 | let rpic = frame_refs.select_ref_pic(0, 0); | |
711 | let weight = &slice_hdr.get_weight(0, 0); | |
712 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
713 | }, | |
714 | MBType::P16x16 => { | |
715 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
716 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) { | |
717 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?; | |
718 | } | |
719 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
720 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
721 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
722 | }, | |
723 | MBType::P16x8 | MBType::P8x16 => { | |
724 | let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 { | |
725 | (16, 8, 0, 8) | |
726 | } else { | |
727 | (8, 16, 8, 0) | |
728 | }; | |
729 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
730 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) { | |
731 | wait_for_mb(disp, sstate, xpos + bw, ypos + bh, mv, ref_id)?; | |
732 | } | |
733 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
734 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
735 | do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight, mc_dsp); | |
736 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
737 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[1].index()) { | |
738 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?; | |
739 | } | |
740 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index()); | |
741 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index()); | |
742 | do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight, mc_dsp); | |
743 | }, | |
744 | MBType::P8x8 | MBType::P8x8Ref0 => { | |
745 | for part in 0..4 { | |
746 | let bx = (part & 1) * 8; | |
747 | let by = (part & 2) * 4; | |
748 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
749 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
750 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index()); | |
751 | ||
752 | match mb_info.sub_mb_type[part] { | |
753 | SubMBType::P8x8 => { | |
754 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
755 | wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?; | |
756 | } | |
757 | do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight, mc_dsp); | |
758 | }, | |
759 | SubMBType::P8x4 => { | |
760 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
761 | wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 4, mv, ref_id)?; | |
762 | } | |
763 | do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic, weight, mc_dsp); | |
764 | let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0]; | |
765 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
766 | wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?; | |
767 | } | |
768 | do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight, mc_dsp); | |
769 | }, | |
770 | SubMBType::P4x8 => { | |
771 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
772 | wait_for_mb(disp, sstate, xpos + bx + 4, ypos + by + 8, mv, ref_id)?; | |
773 | } | |
774 | do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic, weight, mc_dsp); | |
775 | let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0]; | |
776 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
777 | wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?; | |
778 | } | |
779 | do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight, mc_dsp); | |
780 | }, | |
781 | SubMBType::P4x4 => { | |
782 | for sb_no in 0..4 { | |
783 | let sxpos = xpos + bx + (sb_no & 1) * 4; | |
784 | let sypos = ypos + by + (sb_no & 2) * 2; | |
785 | let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4; | |
786 | let mv = sstate.get_cur_blk4(sblk_no).mv[0]; | |
787 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) { | |
788 | wait_for_mb(disp, sstate, sxpos + 4, sypos + 4, mv, ref_id)?; | |
789 | } | |
790 | do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic, weight, mc_dsp); | |
791 | } | |
792 | }, | |
793 | _ => unreachable!(), | |
794 | }; | |
795 | } | |
796 | }, | |
797 | MBType::B16x16(mode) => { | |
798 | let mv0 = sstate.get_cur_blk4(0).mv[0]; | |
799 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
800 | let mv1 = sstate.get_cur_blk4(0).mv[1]; | |
801 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index()); | |
802 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]); | |
803 | wait_b_mc(disp, sstate, frame_refs, [mv0, mv1], [mb_info.ref_l0[0], mb_info.ref_l1[0]], xpos, ypos, 16, 16)?; | |
804 | do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
805 | }, | |
806 | MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { | |
807 | let (pw, ph) = mb_info.mb_type.size(); | |
808 | let (px, py) = (pw & 8, ph & 8); | |
809 | let modes = [mode0, mode1]; | |
810 | let (mut bx, mut by) = (0, 0); | |
811 | for part in 0..2 { | |
812 | let blk = if part == 0 { 0 } else { (px / 4) + py }; | |
813 | let mv0 = sstate.get_cur_blk4(blk).mv[0]; | |
814 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
815 | let mv1 = sstate.get_cur_blk4(blk).mv[1]; | |
816 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index()); | |
817 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]); | |
818 | wait_b_mc(disp, sstate, frame_refs, [mv0, mv1], [mb_info.ref_l0[part], mb_info.ref_l1[part]], xpos + bx, ypos + by, pw, ph)?; | |
819 | do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
820 | bx += px; | |
821 | by += py; | |
822 | } | |
823 | }, | |
824 | MBType::Direct | MBType::BSkip => { | |
825 | if let Some(ref_id) = frame_refs.get_ref_id(1, mb_info.ref_l1[0].index()) { | |
826 | wait_for_mb(disp, sstate, xpos, ypos, ZERO_MV, ref_id)?; | |
827 | } | |
828 | let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type; | |
829 | let is_16x16 = colo_mb_type.is_16x16_ref(); | |
830 | ||
831 | if is_16x16 { | |
832 | let mv = sstate.get_cur_blk4(0).mv; | |
833 | let ref_idx = sstate.get_cur_blk8(0).ref_idx; | |
834 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
835 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
836 | if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) { | |
837 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[0], ref_id)?; | |
838 | } | |
839 | if let Some(ref_id) = frame_refs.get_ref_id(1, mb_info.ref_l1[0].index()) { | |
840 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[1], ref_id)?; | |
841 | } | |
842 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
843 | wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos, ypos, 16, 16)?; | |
844 | do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
845 | } else { | |
846 | for blk4 in 0..16 { | |
847 | let mv = sstate.get_cur_blk4(blk4).mv; | |
848 | let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx; | |
849 | if let Some(ref_id) = frame_refs.get_ref_id(0, ref_idx[0].index()) { | |
850 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[0], ref_id)?; | |
851 | } | |
852 | if let Some(ref_id) = frame_refs.get_ref_id(1, ref_idx[1].index()) { | |
853 | wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[1], ref_id)?; | |
854 | } | |
855 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
856 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
857 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
858 | wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, 4, 4)?; | |
859 | do_b_mc(frm, BMode::Bi, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
860 | } | |
861 | } | |
862 | sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); }); | |
863 | }, | |
864 | MBType::B8x8 => { | |
865 | for part in 0..4 { | |
866 | let ridx = sstate.get_cur_blk8(part).ref_idx; | |
867 | let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index()); | |
868 | let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index()); | |
869 | let subtype = mb_info.sub_mb_type[part]; | |
870 | let blk8 = (part & 1) * 2 + (part & 2) * 4; | |
871 | let mut bx = (part & 1) * 8; | |
872 | let mut by = (part & 2) * 4; | |
873 | match subtype { | |
874 | SubMBType::Direct8x8 => { | |
875 | for blk in 0..4 { | |
876 | let mv = sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv; | |
877 | let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx; | |
878 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
879 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
880 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
881 | wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos + bx, ypos + by, 4, 4)?; | |
882 | do_b_mc(frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
883 | bx += 4; | |
884 | if blk == 1 { | |
885 | bx -= 8; | |
886 | by += 4; | |
887 | } | |
888 | } | |
889 | sstate.get_cur_blk8(part).ref_idx[0].set_direct(); | |
890 | sstate.get_cur_blk8(part).ref_idx[1].set_direct(); | |
891 | }, | |
892 | SubMBType::B8x8(mode) => { | |
893 | let mv = sstate.get_cur_blk4(blk8).mv; | |
894 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
895 | wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, 8, 8)?; | |
896 | do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
897 | }, | |
898 | SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => { | |
899 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
900 | let (pw, ph) = subtype.size(); | |
901 | let mv = sstate.get_cur_blk4(blk8).mv; | |
902 | wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, pw, ph)?; | |
903 | do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
904 | let addr2 = blk8 + (pw & 4) / 4 + (ph & 4); | |
905 | let mv = sstate.get_cur_blk4(addr2).mv; | |
906 | wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph)?; | |
907 | do_b_mc(frm, mode, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
908 | }, | |
909 | SubMBType::B4x4(mode) => { | |
910 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
911 | for i in 0..4 { | |
912 | let addr2 = blk8 + (i & 1) + (i & 2) * 2; | |
913 | let mv = sstate.get_cur_blk4(addr2).mv; | |
914 | wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, 4, 4)?; | |
915 | do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
916 | bx += 4; | |
917 | if i == 1 { | |
918 | bx -= 8; | |
919 | by += 4; | |
920 | } | |
921 | } | |
922 | }, | |
923 | _ => unreachable!(), | |
924 | }; | |
925 | } | |
926 | }, | |
927 | }; | |
928 | if !mb_info.mb_type.is_skip() { | |
929 | if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 { | |
930 | add_luma(frm, sstate, mb_info); | |
931 | } | |
932 | add_chroma(frm, sstate, mb_info); | |
933 | } | |
934 | Ok(()) | |
935 | } |