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