h264: reduce number of arguments for mc_blocks()
[nihav.git] / nihav-itu / src / codecs / h264 / mb_recon.rs
CommitLineData
11d7aef2 1use nihav_core::codecs::{DecoderResult, DecoderError};
495b7ec0 2use nihav_core::frame::*;
11d7aef2
KS
3use nihav_codec_support::codecs::{MV, ZERO_MV};
4use super::{CurrentMBInfo, I4X4_SCAN, Shareable};
5use super::dispatch::{ThreadDispatcher, FrameDecodingStatus};
495b7ec0 6use super::dsp::*;
56a17e69 7use super::pic_ref::SliceRefs;
495b7ec0
KS
8use super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO};
9use super::types::*;
10
11fn 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
170fn 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
193fn 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
2f9923e6 208fn do_p_mc(frm: &mut NASimpleVideoFrame<u8>, xpos: usize, ypos: usize, w: usize, h: usize, mv: MV, ref_pic: Option<NAVideoBufferRef<u8>>, weight: &WeightInfo, mc_dsp: &mut H264MC) {
495b7ec0
KS
209 if let Some(buf) = ref_pic {
210 if !weight.is_weighted() {
2f9923e6 211 mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv);
495b7ec0 212 } else {
834e7b28
KS
213 let mut tmp = McBlock::new();
214 mc_dsp.mc_blocks(&mut tmp, buf, xpos, ypos, w, h, mv);
495b7ec0
KS
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 };
76431444
KS
222 let wmode = match w {
223 2 => 0,
224 4 => 1,
225 8 => 2,
226 _ => 3,
227 };
834e7b28 228 (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp.y, h, yw);
495b7ec0
KS
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 };
834e7b28 238 let csrc = if chroma == 0 { &tmp.u } else { &tmp.v };
76431444 239 (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw);
495b7ec0
KS
240 }
241 }
242 } else {
2f9923e6 243 mc_dsp.gray_block(frm, xpos, ypos, w, h);
495b7ec0
KS
244 }
245}
246
42005e25 247#[allow(clippy::match_like_matches_macro)]
2f9923e6 248fn do_b_mc(frm: &mut NASimpleVideoFrame<u8>, mode: BMode, xpos: usize, ypos: usize, w: usize, h: usize, mv0: MV, ref_pic0: Option<NAVideoBufferRef<u8>>, weight0: &WeightInfo, mv1: MV, ref_pic1: Option<NAVideoBufferRef<u8>>, weight1: &WeightInfo, mc_dsp: &mut H264MC) {
495b7ec0
KS
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 {
2f9923e6 259 mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv0);
495b7ec0 260 } else {
2f9923e6 261 mc_dsp.gray_block(frm, xpos, ypos, w, h);
495b7ec0
KS
262 }
263 },
264 BMode::L1 => {
265 if let Some(buf) = ref_pic1 {
2f9923e6 266 mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv1);
495b7ec0 267 } else {
2f9923e6 268 mc_dsp.gray_block(frm, xpos, ypos, w, h);
495b7ec0
KS
269 }
270 },
271 BMode::Bi => {
272 match (ref_pic0, ref_pic1) {
273 (Some(buf0), Some(buf1)) => {
2f9923e6
KS
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);
495b7ec0
KS
276 },
277 (Some(buf0), None) => {
2f9923e6 278 mc_dsp.do_mc(frm, buf0, xpos, ypos, w, h, mv0);
495b7ec0
KS
279 },
280 (None, Some(buf1)) => {
2f9923e6 281 mc_dsp.do_mc(frm, buf1, xpos, ypos, w, h, mv1);
495b7ec0
KS
282 },
283 (None, None) => {
2f9923e6 284 mc_dsp.gray_block(frm, xpos, ypos, w, h);
495b7ec0
KS
285 },
286 };
287 },
288 };
289 } else {
834e7b28
KS
290 let mut tmp0 = McBlock::new();
291 let mut tmp1 = McBlock::new();
495b7ec0
KS
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) };
834e7b28 295 mc_dsp.mc_blocks(&mut tmp0, buf, xpos, ypos, w, h, mv);
495b7ec0
KS
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 };
76431444
KS
303 let wmode = match w {
304 2 => 0,
305 4 => 1,
306 8 => 2,
307 _ => 3,
308 };
834e7b28 309 (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp0.y, h, yw);
495b7ec0
KS
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 };
834e7b28 319 let csrc = if chroma == 0 { &tmp0.u } else { &tmp0.v };
76431444 320 (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw);
495b7ec0
KS
321 }
322 },
323 (BMode::Bi, Some(buf0), Some(buf1)) => { // do both and avg
834e7b28
KS
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);
495b7ec0
KS
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 };
76431444
KS
334 let wmode = match w {
335 2 => 0,
336 4 => 1,
337 8 => 2,
338 _ => 3,
339 };
834e7b28 340 (mc_dsp.put_block_weighted2[wmode])(&mut frm.data[yoff..], frm.stride[0], &tmp0.y, &tmp1.y, h, yw);
495b7ec0
KS
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 };
834e7b28
KS
355 let csrc0 = if chroma == 0 { &tmp0.u } else { &tmp0.v };
356 let csrc1 = if chroma == 0 { &tmp1.u } else { &tmp1.v };
76431444 357 (mc_dsp.put_block_weighted2[wmode - 1])(&mut frm.data[coff..], cstride, csrc0, csrc1, h / 2, cw);
495b7ec0
KS
358 }
359 },
360 _ => {
2f9923e6 361 mc_dsp.gray_block(frm, xpos, ypos, w, h);
495b7ec0
KS
362 },
363 };
364 }
365}
366
56a17e69 367fn get_weights(slice_hdr: &SliceHeader, frame_refs: &SliceRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) {
495b7ec0
KS
368 let idx_l0 = ref_l0.index();
369 let idx_l1 = ref_l1.index();
370 if mode != BMode::Bi || weight_mode != 2 {
371 (slice_hdr.get_weight(0, idx_l0), slice_hdr.get_weight(1, idx_l1))
372 } 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)) {
373 let r0_poc = pic0.full_id as u16;
374 let r1_poc = pic1.full_id as u16;
375 let cur_id = frame_refs.cur_id as u16;
376 if (r0_poc == r1_poc) || pic0.long_term.is_some() || pic1.long_term.is_some() {
377 return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO);
378 }
379
380 let td = (i32::from(r1_poc) - i32::from(r0_poc)).max(-128).min(127);
381 let tx = (16384 + (td / 2).abs()) / td;
382 let tb = (i32::from(cur_id) - i32::from(r0_poc)).max(-128).min(127);
383 let scale = ((tb * tx + 32) >> 6).max(-1024).min(1023);
384 if scale == 128 || (scale >> 2) < -64 || (scale >> 2) > 128 {
385 return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO);
386 }
387 let w1 = (scale >> 2) as i8;
388 let w0 = 64 - w1;
389
390 let weight0 = WeightInfo {
391 luma_weighted: true,
392 luma_weight: w0,
393 luma_offset: 0,
394 luma_shift: 5,
395 chroma_weighted: true,
396 chroma_weight: [w0; 2],
397 chroma_offset: [0; 2],
398 chroma_shift: 5,
399 };
400 let weight1 = WeightInfo {
401 luma_weighted: true,
402 luma_weight: w1,
403 luma_offset: 0,
404 luma_shift: 5,
405 chroma_weighted: true,
406 chroma_weight: [w1; 2],
407 chroma_offset: [0; 2],
408 chroma_shift: 5,
409 };
410
411 (weight0, weight1)
412 } else {
413 (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO)
414 }
415}
416
56a17e69 417pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &SliceRefs, mc_dsp: &mut H264MC, weight_mode: u8) {
495b7ec0
KS
418 let xpos = sstate.mb_x * 16;
419 let ypos = sstate.mb_y * 16;
420
421 match mb_info.mb_type {
422 MBType::Intra16x16(_, _, _) => {
42005e25 423 pred_intra(frm, sstate, mb_info);
495b7ec0
KS
424 },
425 MBType::Intra4x4 | MBType::Intra8x8 => {
42005e25 426 pred_intra(frm, sstate, mb_info);
495b7ec0
KS
427 },
428 MBType::PCM => {},
429 MBType::PSkip => {
430 let mv = sstate.get_cur_blk4(0).mv[0];
431 let rpic = frame_refs.select_ref_pic(0, 0);
432 let weight = &slice_hdr.get_weight(0, 0);
2f9923e6 433 do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp);
495b7ec0
KS
434 },
435 MBType::P16x16 => {
436 let mv = sstate.get_cur_blk4(0).mv[0];
437 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
438 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index());
2f9923e6 439 do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp);
495b7ec0
KS
440 },
441 MBType::P16x8 | MBType::P8x16 => {
442 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
443 (16, 8, 0, 8)
444 } else {
445 (8, 16, 8, 0)
446 };
447 let mv = sstate.get_cur_blk4(0).mv[0];
448 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
449 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index());
2f9923e6 450 do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight, mc_dsp);
495b7ec0
KS
451 let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0];
452 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index());
453 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index());
2f9923e6 454 do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight, mc_dsp);
495b7ec0
KS
455 },
456 MBType::P8x8 | MBType::P8x8Ref0 => {
457 for part in 0..4 {
458 let bx = (part & 1) * 8;
459 let by = (part & 2) * 4;
460 let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0];
461 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
462 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index());
463
464 match mb_info.sub_mb_type[part] {
465 SubMBType::P8x8 => {
2f9923e6 466 do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight, mc_dsp);
495b7ec0
KS
467 },
468 SubMBType::P8x4 => {
2f9923e6 469 do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic.clone(), weight, mc_dsp);
495b7ec0 470 let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0];
2f9923e6 471 do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight, mc_dsp);
495b7ec0
KS
472 },
473 SubMBType::P4x8 => {
2f9923e6 474 do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic.clone(), weight, mc_dsp);
495b7ec0 475 let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0];
2f9923e6 476 do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight, mc_dsp);
495b7ec0
KS
477 },
478 SubMBType::P4x4 => {
479 for sb_no in 0..4 {
480 let sxpos = xpos + bx + (sb_no & 1) * 4;
481 let sypos = ypos + by + (sb_no & 2) * 2;
482 let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4;
483 let mv = sstate.get_cur_blk4(sblk_no).mv[0];
2f9923e6 484 do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic.clone(), weight, mc_dsp);
495b7ec0
KS
485 }
486 },
487 _ => unreachable!(),
488 };
489 }
490 },
491 MBType::B16x16(mode) => {
492 let mv0 = sstate.get_cur_blk4(0).mv[0];
493 let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
494 let mv1 = sstate.get_cur_blk4(0).mv[1];
495 let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index());
496 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]);
2f9923e6 497 do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp);
495b7ec0
KS
498 },
499 MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => {
500 let (pw, ph) = mb_info.mb_type.size();
501 let (px, py) = (pw & 8, ph & 8);
502 let modes = [mode0, mode1];
503 let (mut bx, mut by) = (0, 0);
504 for part in 0..2 {
505 let blk = if part == 0 { 0 } else { (px / 4) + py };
506 let mv0 = sstate.get_cur_blk4(blk).mv[0];
507 let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
508 let mv1 = sstate.get_cur_blk4(blk).mv[1];
509 let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index());
510 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]);
2f9923e6 511 do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp);
495b7ec0
KS
512 bx += px;
513 by += py;
514 }
515 },
516 MBType::Direct | MBType::BSkip => {
517 let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type;
518 let is_16x16 = colo_mb_type.is_16x16_ref();
519
520 if is_16x16 {
521 let mv = sstate.get_cur_blk4(0).mv;
522 let ref_idx = sstate.get_cur_blk8(0).ref_idx;
523 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
524 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
525 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
2f9923e6 526 do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
495b7ec0
KS
527 } else {
528 for blk4 in 0..16 {
529 let mv = sstate.get_cur_blk4(blk4).mv;
530 let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx;
531 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
532 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
533 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
2f9923e6 534 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);
495b7ec0
KS
535 }
536 }
537 sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
538 },
539 MBType::B8x8 => {
540 for part in 0..4 {
541 let ridx = sstate.get_cur_blk8(part).ref_idx;
542 let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index());
543 let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index());
544 let subtype = mb_info.sub_mb_type[part];
545 let blk8 = (part & 1) * 2 + (part & 2) * 4;
546 let mut bx = (part & 1) * 8;
547 let mut by = (part & 2) * 4;
548 match subtype {
549 SubMBType::Direct8x8 => {
550 for blk in 0..4 {
551 let mv = sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv;
552 let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx;
553 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
554 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
555 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
2f9923e6 556 do_b_mc(frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
495b7ec0
KS
557 bx += 4;
558 if blk == 1 {
559 bx -= 8;
560 by += 4;
561 }
562 }
563 sstate.get_cur_blk8(part).ref_idx[0].set_direct();
564 sstate.get_cur_blk8(part).ref_idx[1].set_direct();
565 },
566 SubMBType::B8x8(mode) => {
567 let mv = sstate.get_cur_blk4(blk8).mv;
568 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
2f9923e6 569 do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
495b7ec0
KS
570 },
571 SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => {
572 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
573 let (pw, ph) = subtype.size();
574 let mv = sstate.get_cur_blk4(blk8).mv;
2f9923e6 575 do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp);
495b7ec0
KS
576 let addr2 = blk8 + (pw & 4) / 4 + (ph & 4);
577 let mv = sstate.get_cur_blk4(addr2).mv;
2f9923e6 578 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);
495b7ec0
KS
579 },
580 SubMBType::B4x4(mode) => {
581 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
582 for i in 0..4 {
583 let addr2 = blk8 + (i & 1) + (i & 2) * 2;
584 let mv = sstate.get_cur_blk4(addr2).mv;
2f9923e6 585 do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp);
495b7ec0
KS
586 bx += 4;
587 if i == 1 {
588 bx -= 8;
589 by += 4;
590 }
591 }
592 },
593 _ => unreachable!(),
594 };
595 }
596 },
597 };
598 if !mb_info.mb_type.is_skip() {
599 if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
42005e25 600 add_luma(frm, sstate, mb_info);
495b7ec0 601 }
42005e25 602 add_chroma(frm, sstate, mb_info);
495b7ec0
KS
603 }
604}
11d7aef2
KS
605
606pub fn wait_for_mb(disp: &Shareable<ThreadDispatcher>, sstate: &SliceState, xpos: usize, ypos: usize, mv: MV, ref_id: u32) -> DecoderResult<()> {
607 let xpos = xpos as isize + ((mv.x >> 2) as isize) + 4;
608 let ypos = ypos as isize + ((mv.y >> 2) as isize) + 4;
609 let dst_mb_x = ((xpos.max(0) as usize) / 16).min(sstate.mb_w - 1);
610 let dst_mb_y = ((ypos.max(0) as usize) / 16).min(sstate.mb_h - 1);
611 let expected_mb = dst_mb_x + dst_mb_y * sstate.mb_w;
612 loop {
613 if let Ok(ds) = disp.read() {
614 match ds.check_pos(ref_id, expected_mb) {
615 FrameDecodingStatus::Ok => return Ok(()),
616 FrameDecodingStatus::NotReady => {},
617 _ => return Err(DecoderError::MissingReference),
618 };
619 }
620 std::thread::yield_now();
621 }
622}
623
624fn wait_b_mc(disp: &Shareable<ThreadDispatcher>, sstate: &SliceState, frame_refs: &SliceRefs, mv: [MV; 2], ref_idx: [PicRef; 2], xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> {
625 if let Some(ref_id) = frame_refs.get_ref_id(0, ref_idx[0].index()) {
626 wait_for_mb(disp, sstate, xpos + w, ypos + h, mv[0], ref_id)?;
627 }
628 if let Some(ref_id) = frame_refs.get_ref_id(1, ref_idx[1].index()) {
629 wait_for_mb(disp, sstate, xpos + w, ypos + h, mv[1], ref_id)?;
630 }
631 Ok(())
632}
633
634pub fn recon_mb_mt(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &SliceRefs, mc_dsp: &mut H264MC, weight_mode: u8, disp: &Shareable<ThreadDispatcher>) -> DecoderResult<()> {
635 let xpos = sstate.mb_x * 16;
636 let ypos = sstate.mb_y * 16;
637
638 match mb_info.mb_type {
639 MBType::Intra16x16(_, _, _) => {
640 pred_intra(frm, sstate, mb_info);
641 },
642 MBType::Intra4x4 | MBType::Intra8x8 => {
643 pred_intra(frm, sstate, mb_info);
644 },
645 MBType::PCM => {},
646 MBType::PSkip => {
647 let mv = sstate.get_cur_blk4(0).mv[0];
648 if let Some(ref_id) = frame_refs.get_ref_id(0, 0) {
649 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?;
650 }
651 let rpic = frame_refs.select_ref_pic(0, 0);
652 let weight = &slice_hdr.get_weight(0, 0);
653 do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp);
654 },
655 MBType::P16x16 => {
656 let mv = sstate.get_cur_blk4(0).mv[0];
657 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) {
658 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?;
659 }
660 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
661 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index());
662 do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp);
663 },
664 MBType::P16x8 | MBType::P8x16 => {
665 let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 {
666 (16, 8, 0, 8)
667 } else {
668 (8, 16, 8, 0)
669 };
670 let mv = sstate.get_cur_blk4(0).mv[0];
671 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) {
672 wait_for_mb(disp, sstate, xpos + bw, ypos + bh, mv, ref_id)?;
673 }
674 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
675 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index());
676 do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight, mc_dsp);
677 let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0];
678 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[1].index()) {
679 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv, ref_id)?;
680 }
681 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index());
682 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index());
683 do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight, mc_dsp);
684 },
685 MBType::P8x8 | MBType::P8x8Ref0 => {
686 for part in 0..4 {
687 let bx = (part & 1) * 8;
688 let by = (part & 2) * 4;
689 let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0];
690 let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
691 let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index());
692
693 match mb_info.sub_mb_type[part] {
694 SubMBType::P8x8 => {
695 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
696 wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?;
697 }
698 do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight, mc_dsp);
699 },
700 SubMBType::P8x4 => {
701 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
702 wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 4, mv, ref_id)?;
703 }
704 do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic.clone(), weight, mc_dsp);
705 let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0];
706 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
707 wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?;
708 }
709 do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight, mc_dsp);
710 },
711 SubMBType::P4x8 => {
712 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
713 wait_for_mb(disp, sstate, xpos + bx + 4, ypos + by + 8, mv, ref_id)?;
714 }
715 do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic.clone(), weight, mc_dsp);
716 let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0];
717 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
718 wait_for_mb(disp, sstate, xpos + bx + 8, ypos + by + 8, mv, ref_id)?;
719 }
720 do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight, mc_dsp);
721 },
722 SubMBType::P4x4 => {
723 for sb_no in 0..4 {
724 let sxpos = xpos + bx + (sb_no & 1) * 4;
725 let sypos = ypos + by + (sb_no & 2) * 2;
726 let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4;
727 let mv = sstate.get_cur_blk4(sblk_no).mv[0];
728 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[part].index()) {
729 wait_for_mb(disp, sstate, sxpos + 4, sypos + 4, mv, ref_id)?;
730 }
731 do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic.clone(), weight, mc_dsp);
732 }
733 },
734 _ => unreachable!(),
735 };
736 }
737 },
738 MBType::B16x16(mode) => {
739 let mv0 = sstate.get_cur_blk4(0).mv[0];
740 let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index());
741 let mv1 = sstate.get_cur_blk4(0).mv[1];
742 let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index());
743 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]);
744 wait_b_mc(disp, sstate, frame_refs, [mv0, mv1], [mb_info.ref_l0[0], mb_info.ref_l1[0]], xpos, ypos, 16, 16)?;
745 do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp);
746 },
747 MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => {
748 let (pw, ph) = mb_info.mb_type.size();
749 let (px, py) = (pw & 8, ph & 8);
750 let modes = [mode0, mode1];
751 let (mut bx, mut by) = (0, 0);
752 for part in 0..2 {
753 let blk = if part == 0 { 0 } else { (px / 4) + py };
754 let mv0 = sstate.get_cur_blk4(blk).mv[0];
755 let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index());
756 let mv1 = sstate.get_cur_blk4(blk).mv[1];
757 let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index());
758 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]);
759 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)?;
760 do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp);
761 bx += px;
762 by += py;
763 }
764 },
765 MBType::Direct | MBType::BSkip => {
766 if let Some(ref_id) = frame_refs.get_ref_id(1, mb_info.ref_l1[0].index()) {
767 wait_for_mb(disp, sstate, xpos, ypos, ZERO_MV, ref_id)?;
768 }
769 let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type;
770 let is_16x16 = colo_mb_type.is_16x16_ref();
771
772 if is_16x16 {
773 let mv = sstate.get_cur_blk4(0).mv;
774 let ref_idx = sstate.get_cur_blk8(0).ref_idx;
775 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
776 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
777 if let Some(ref_id) = frame_refs.get_ref_id(0, mb_info.ref_l0[0].index()) {
778 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[0], ref_id)?;
779 }
780 if let Some(ref_id) = frame_refs.get_ref_id(1, mb_info.ref_l1[0].index()) {
781 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[1], ref_id)?;
782 }
783 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
784 wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos, ypos, 16, 16)?;
785 do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
786 } else {
787 for blk4 in 0..16 {
788 let mv = sstate.get_cur_blk4(blk4).mv;
789 let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx;
790 if let Some(ref_id) = frame_refs.get_ref_id(0, ref_idx[0].index()) {
791 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[0], ref_id)?;
792 }
793 if let Some(ref_id) = frame_refs.get_ref_id(1, ref_idx[1].index()) {
794 wait_for_mb(disp, sstate, xpos + 16, ypos + 16, mv[1], ref_id)?;
795 }
796 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
797 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
798 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
799 wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, 4, 4)?;
800 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);
801 }
802 }
803 sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); });
804 },
805 MBType::B8x8 => {
806 for part in 0..4 {
807 let ridx = sstate.get_cur_blk8(part).ref_idx;
808 let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index());
809 let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index());
810 let subtype = mb_info.sub_mb_type[part];
811 let blk8 = (part & 1) * 2 + (part & 2) * 4;
812 let mut bx = (part & 1) * 8;
813 let mut by = (part & 2) * 4;
814 match subtype {
815 SubMBType::Direct8x8 => {
816 for blk in 0..4 {
817 let mv = sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv;
818 let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx;
819 let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index());
820 let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index());
821 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]);
822 wait_b_mc(disp, sstate, frame_refs, mv, ref_idx, xpos + bx, ypos + by, 4, 4)?;
823 do_b_mc(frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
824 bx += 4;
825 if blk == 1 {
826 bx -= 8;
827 by += 4;
828 }
829 }
830 sstate.get_cur_blk8(part).ref_idx[0].set_direct();
831 sstate.get_cur_blk8(part).ref_idx[1].set_direct();
832 },
833 SubMBType::B8x8(mode) => {
834 let mv = sstate.get_cur_blk4(blk8).mv;
835 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
836 wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, 8, 8)?;
837 do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp);
838 },
839 SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => {
840 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
841 let (pw, ph) = subtype.size();
842 let mv = sstate.get_cur_blk4(blk8).mv;
843 wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, pw, ph)?;
844 do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp);
845 let addr2 = blk8 + (pw & 4) / 4 + (ph & 4);
846 let mv = sstate.get_cur_blk4(addr2).mv;
847 wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph)?;
848 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);
849 },
850 SubMBType::B4x4(mode) => {
851 let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]);
852 for i in 0..4 {
853 let addr2 = blk8 + (i & 1) + (i & 2) * 2;
854 let mv = sstate.get_cur_blk4(addr2).mv;
855 wait_b_mc(disp, sstate, frame_refs, mv, ridx, xpos + bx, ypos + by, 4, 4)?;
856 do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp);
857 bx += 4;
858 if i == 1 {
859 bx -= 8;
860 by += 4;
861 }
862 }
863 },
864 _ => unreachable!(),
865 };
866 }
867 },
868 };
869 if !mb_info.mb_type.is_skip() {
870 if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 {
871 add_luma(frm, sstate, mb_info);
872 }
873 add_chroma(frm, sstate, mb_info);
874 }
875 Ok(())
876}