Commit | Line | Data |
---|---|---|
11d7aef2 | 1 | use nihav_core::codecs::{DecoderResult, DecoderError}; |
495b7ec0 | 2 | use nihav_core::frame::*; |
11d7aef2 KS |
3 | use nihav_codec_support::codecs::{MV, ZERO_MV}; |
4 | use super::{CurrentMBInfo, I4X4_SCAN, Shareable}; | |
5 | use super::dispatch::{ThreadDispatcher, FrameDecodingStatus}; | |
495b7ec0 | 6 | use super::dsp::*; |
56a17e69 | 7 | use super::pic_ref::SliceRefs; |
495b7ec0 KS |
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 | ||
2f9923e6 | 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) { |
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 | 248 | 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) { |
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 | 367 | fn 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 | 417 | 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) { |
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 | |
606 | pub 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 | ||
624 | 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<()> { | |
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 | ||
634 | 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<()> { | |
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 | } |