]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::frame::*; | |
2 | use nihav_codec_support::codecs::MV; | |
3 | use super::{CurrentMBInfo, I4X4_SCAN}; | |
4 | use super::dsp::*; | |
5 | use super::pic_ref::FrameRefs; | |
6 | use super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO}; | |
7 | use super::types::*; | |
8 | ||
9 | fn pred_intra(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
10 | let yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0]; | |
11 | match mb_info.mb_type { | |
12 | MBType::Intra16x16(imode, _, _) => { | |
13 | let id = if imode != 2 || (sstate.has_top && sstate.has_left) { | |
14 | imode as usize | |
15 | } else if !sstate.has_top && !sstate.has_left { | |
16 | IPRED8_DC128 | |
17 | } else if !sstate.has_left { | |
18 | IPRED8_DC_TOP | |
19 | } else { | |
20 | IPRED8_DC_LEFT | |
21 | }; | |
22 | IPRED_FUNCS16X16[id](&mut frm.data[yoff..], frm.stride[0], &sstate.top_line_y[sstate.mb_x * 16..], &sstate.left_y); | |
23 | }, | |
24 | MBType::Intra8x8 => { | |
25 | let mut ictx = IPred8Context::new(); | |
26 | for part in 0..4 { | |
27 | let x = (part & 1) * 2; | |
28 | let y = part & 2; | |
29 | let blk4 = x + y * 4; | |
30 | ||
31 | let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0]; | |
32 | let has_top = y > 0 || sstate.has_top; | |
33 | let has_left = x > 0 || sstate.has_left; | |
34 | let imode = mb_info.ipred[blk4]; | |
35 | let id = if imode != IntraPredMode::DC || (has_top && has_left) { | |
36 | let im_id: u8 = imode.into(); | |
37 | im_id as usize | |
38 | } else if !has_top && !has_left { | |
39 | IPRED4_DC128 | |
40 | } else if !has_left { | |
41 | IPRED4_DC_TOP | |
42 | } else { | |
43 | IPRED4_DC_LEFT | |
44 | }; | |
45 | let mb_idx = sstate.mb_x + sstate.mb_y * sstate.mb_w; | |
46 | let noright = (y == 2 || sstate.mb_x == sstate.mb_w - 1 || mb_idx < sstate.mb_start + sstate.mb_w) && (x == 2); | |
47 | 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); | |
48 | if id != IPRED4_DC128 { | |
49 | let top = if y == 0 { | |
50 | &sstate.top_line_y[sstate.mb_x * 16 + x * 4..] | |
51 | } else { | |
52 | &frm.data[cur_yoff - frm.stride[0]..] | |
53 | }; | |
54 | let mut left_buf = [0; 9]; | |
55 | let left = if x == 0 { | |
56 | &sstate.left_y[y * 4..] | |
57 | } else { | |
58 | if has_tl { | |
59 | if y == 0 { | |
60 | left_buf[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1]; | |
61 | } else { | |
62 | left_buf[0] = frm.data[cur_yoff - 1 - frm.stride[0]]; | |
63 | } | |
64 | } | |
65 | if has_left { | |
66 | for (dst, src) in left_buf[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) { | |
67 | *dst = src[0]; | |
68 | } | |
69 | } | |
70 | &left_buf | |
71 | }; | |
72 | ictx.fill(top, left, has_top, has_top && !noright, has_left, has_tl); | |
73 | } | |
74 | IPRED_FUNCS8X8_LUMA[id](&mut frm.data[cur_yoff..], frm.stride[0], &ictx); | |
75 | if mb_info.coded[blk4] { | |
76 | add_coeffs8(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs8x8[part].coeffs); | |
77 | } | |
78 | } | |
79 | }, | |
80 | MBType::Intra4x4 => { | |
81 | for &(x,y) in I4X4_SCAN.iter() { | |
82 | let x = x as usize; | |
83 | let y = y as usize; | |
84 | let cur_yoff = yoff + x * 4 + y * 4 * frm.stride[0]; | |
85 | let has_top = y > 0 || sstate.has_top; | |
86 | let has_left = x > 0 || sstate.has_left; | |
87 | let imode = mb_info.ipred[x + y * 4]; | |
88 | let id = if imode != IntraPredMode::DC || (has_top && has_left) { | |
89 | let im_id: u8 = imode.into(); | |
90 | im_id as usize | |
91 | } else if !has_top && !has_left { | |
92 | IPRED4_DC128 | |
93 | } else if !has_left { | |
94 | IPRED4_DC_TOP | |
95 | } else { | |
96 | IPRED4_DC_LEFT | |
97 | }; | |
98 | 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); | |
99 | let tr: [u8; 4] = if y == 0 { | |
100 | let tsrc = &sstate.top_line_y[sstate.mb_x * 16 + x * 4..]; | |
101 | if has_top && !noright { | |
102 | [tsrc[4], tsrc[5], tsrc[6], tsrc[7]] | |
103 | } else if has_top { | |
104 | [tsrc[3]; 4] | |
105 | } else { | |
106 | [0; 4] | |
107 | } | |
108 | } else if (x & 1) == 0 || (x == 1 && y == 2) { | |
109 | let i = cur_yoff - frm.stride[0]; | |
110 | [frm.data[i + 4], frm.data[i + 5], frm.data[i + 6], frm.data[i + 7]] | |
111 | } else { | |
112 | let i = cur_yoff - frm.stride[0]; | |
113 | [frm.data[i + 3], frm.data[i + 3], frm.data[i + 3], frm.data[i + 3]] | |
114 | }; | |
115 | let mut top = [128; 4]; | |
116 | let mut left = [128; 9]; | |
117 | if y == 0 { | |
118 | if has_top { | |
119 | top.copy_from_slice(&sstate.top_line_y[sstate.mb_x * 16 + x * 4..][..4]); | |
120 | } | |
121 | } else { | |
122 | top.copy_from_slice(&frm.data[cur_yoff - frm.stride[0]..][..4]); | |
123 | } | |
124 | if x == 0 { | |
125 | if has_left { | |
126 | for (dst, &src) in left.iter_mut().zip(sstate.left_y[y * 4..].iter()) { | |
127 | *dst = src; | |
128 | } | |
129 | } | |
130 | } else { | |
131 | if y == 0 { | |
132 | if x == 0 { | |
133 | left[0] = sstate.left_y[y * 4]; | |
134 | } else if has_top { | |
135 | left[0] = sstate.top_line_y[sstate.mb_x * 16 + x * 4 - 1]; | |
136 | } | |
137 | } else { | |
138 | left[0] = frm.data[cur_yoff - frm.stride[0] - 1]; | |
139 | } | |
140 | for (dst, row) in left[1..].iter_mut().zip(frm.data[cur_yoff - 1..].chunks(frm.stride[0])) { | |
141 | *dst = row[0]; | |
142 | } | |
143 | } | |
144 | IPRED_FUNCS4X4[id](&mut frm.data[cur_yoff..], frm.stride[0], &top, &left, &tr); | |
145 | if mb_info.coded[x + y * 4] { | |
146 | add_coeffs(frm.data, cur_yoff, frm.stride[0], &mb_info.coeffs[x + y * 4]); | |
147 | } | |
148 | } | |
149 | }, | |
150 | _ => unreachable!(), | |
151 | }; | |
152 | let id = if mb_info.chroma_ipred != 0 || (sstate.has_top && sstate.has_left) { | |
153 | mb_info.chroma_ipred as usize | |
154 | } else if !sstate.has_top && !sstate.has_left { | |
155 | IPRED8_DC128 | |
156 | } else if !sstate.has_left { | |
157 | IPRED8_DC_TOP | |
158 | } else { | |
159 | IPRED8_DC_LEFT | |
160 | }; | |
161 | for chroma in 1..3 { | |
162 | let off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma]; | |
163 | let top = &sstate.top_line_c[chroma - 1][sstate.mb_x * 8..]; | |
164 | IPRED_FUNCS8X8_CHROMA[id](&mut frm.data[off..], frm.stride[chroma], top, &sstate.left_c[chroma - 1]); | |
165 | } | |
166 | } | |
167 | ||
168 | fn add_luma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
169 | let mut yoff = frm.offset[0] + sstate.mb_x * 16 + sstate.mb_y * 16 * frm.stride[0]; | |
170 | if !mb_info.transform_size_8x8 { | |
171 | for y in 0..4 { | |
172 | for x in 0..4 { | |
173 | if mb_info.coded[x + y * 4] { | |
174 | add_coeffs(frm.data, yoff + x * 4, frm.stride[0], &mb_info.coeffs[x + y * 4]); | |
175 | } | |
176 | } | |
177 | yoff += frm.stride[0] * 4; | |
178 | } | |
179 | } else { | |
180 | for y in 0..2 { | |
181 | for x in 0..2 { | |
182 | if mb_info.coded[x * 2 + y * 2 * 4] { | |
183 | add_coeffs8(frm.data, yoff + x * 8, frm.stride[0], &mb_info.coeffs8x8[x + y * 2].coeffs); | |
184 | } | |
185 | } | |
186 | yoff += frm.stride[0] * 8; | |
187 | } | |
188 | } | |
189 | } | |
190 | ||
191 | fn add_chroma(frm: &mut NASimpleVideoFrame<u8>, sstate: &SliceState, mb_info: &CurrentMBInfo) { | |
192 | for chroma in 1..3 { | |
193 | let mut off = frm.offset[chroma] + sstate.mb_x * 8 + sstate.mb_y * 8 * frm.stride[chroma]; | |
194 | for y in 0..2 { | |
195 | for x in 0..2 { | |
196 | let blk_no = 16 + (chroma - 1) * 4 + x + y * 2; | |
197 | if mb_info.coded[blk_no] || mb_info.coeffs[blk_no][0] != 0 { | |
198 | add_coeffs(frm.data, off + x * 4, frm.stride[chroma], &mb_info.coeffs[blk_no]); | |
199 | } | |
200 | } | |
201 | off += frm.stride[chroma] * 4; | |
202 | } | |
203 | } | |
204 | } | |
205 | ||
206 | 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) { | |
207 | if let Some(buf) = ref_pic { | |
208 | if !weight.is_weighted() { | |
209 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv); | |
210 | } else { | |
211 | let mut ytmp = [0; 16 * 16]; | |
212 | let mut utmp = [0; 16 * 16]; | |
213 | let mut vtmp = [0; 16 * 16]; | |
214 | mc_dsp.mc_blocks(&mut ytmp, &mut utmp, &mut vtmp, buf, xpos, ypos, w, h, mv); | |
215 | ||
216 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
217 | let yw = if weight.luma_weighted { | |
218 | [weight.luma_weight, weight.luma_offset, weight.luma_shift as i8] | |
219 | } else { | |
220 | [1, 0, 0] | |
221 | }; | |
222 | let wmode = match w { | |
223 | 2 => 0, | |
224 | 4 => 1, | |
225 | 8 => 2, | |
226 | _ => 3, | |
227 | }; | |
228 | (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &ytmp, h, yw); | |
229 | ||
230 | for chroma in 0..2 { | |
231 | let cstride = frm.stride[chroma + 1]; | |
232 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
233 | let cw = if weight.chroma_weighted { | |
234 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
235 | } else { | |
236 | [1, 0, 0] | |
237 | }; | |
238 | let csrc = if chroma == 0 { &utmp } else { &vtmp }; | |
239 | (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw); | |
240 | } | |
241 | } | |
242 | } else { | |
243 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
244 | } | |
245 | } | |
246 | ||
247 | #[allow(clippy::match_like_matches_macro)] | |
248 | fn do_b_mc(frm: &mut NASimpleVideoFrame<u8>, mode: BMode, xpos: usize, ypos: usize, w: usize, h: usize, mv0: MV, ref_pic0: Option<NAVideoBufferRef<u8>>, weight0: &WeightInfo, mv1: MV, ref_pic1: Option<NAVideoBufferRef<u8>>, weight1: &WeightInfo, mc_dsp: &mut H264MC) { | |
249 | let do_weight = match (mode, weight0.is_weighted(), weight1.is_weighted()) { | |
250 | (BMode::L0, true, _) => true, | |
251 | (BMode::L1, _, true) => true, | |
252 | (BMode::Bi, true, true) => true, | |
253 | _ => false, | |
254 | }; | |
255 | if !do_weight { | |
256 | match mode { | |
257 | BMode::L0 => { | |
258 | if let Some(buf) = ref_pic0 { | |
259 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv0); | |
260 | } else { | |
261 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
262 | } | |
263 | }, | |
264 | BMode::L1 => { | |
265 | if let Some(buf) = ref_pic1 { | |
266 | mc_dsp.do_mc(frm, buf, xpos, ypos, w, h, mv1); | |
267 | } else { | |
268 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
269 | } | |
270 | }, | |
271 | BMode::Bi => { | |
272 | match (ref_pic0, ref_pic1) { | |
273 | (Some(buf0), Some(buf1)) => { | |
274 | mc_dsp.do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
275 | mc_dsp.do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1); | |
276 | }, | |
277 | (Some(buf0), None) => { | |
278 | mc_dsp.do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
279 | }, | |
280 | (None, Some(buf1)) => { | |
281 | mc_dsp.do_mc(frm, buf1, xpos, ypos, w, h, mv1); | |
282 | }, | |
283 | (None, None) => { | |
284 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
285 | }, | |
286 | }; | |
287 | }, | |
288 | }; | |
289 | } else { | |
290 | let mut ytmp0 = [0x80; 16 * 16]; | |
291 | let mut utmp0 = [0x80; 16 * 16]; | |
292 | let mut vtmp0 = [0x80; 16 * 16]; | |
293 | let mut ytmp1 = [0x80; 16 * 16]; | |
294 | let mut utmp1 = [0x80; 16 * 16]; | |
295 | let mut vtmp1 = [0x80; 16 * 16]; | |
296 | match (mode, ref_pic0, ref_pic1) { | |
297 | (BMode::L0, Some(buf), _) | (BMode::L1, _, Some(buf)) => { | |
298 | let (mv, weight) = if mode == BMode::L0 { (mv0, weight0) } else { (mv1, weight1) }; | |
299 | mc_dsp.mc_blocks(&mut ytmp0, &mut utmp0, &mut vtmp0, buf, xpos, ypos, w, h, mv); | |
300 | ||
301 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
302 | let yw = if weight.luma_weighted { | |
303 | [weight.luma_weight, weight.luma_offset, weight.luma_shift as i8] | |
304 | } else { | |
305 | [1, 0, 0] | |
306 | }; | |
307 | let wmode = match w { | |
308 | 2 => 0, | |
309 | 4 => 1, | |
310 | 8 => 2, | |
311 | _ => 3, | |
312 | }; | |
313 | (mc_dsp.put_block_weighted[wmode])(&mut frm.data[yoff..], frm.stride[0], &ytmp0, h, yw); | |
314 | ||
315 | for chroma in 0..2 { | |
316 | let cstride = frm.stride[chroma + 1]; | |
317 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
318 | let cw = if weight.chroma_weighted { | |
319 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
320 | } else { | |
321 | [1, 0, 0] | |
322 | }; | |
323 | let csrc = if chroma == 0 { &utmp0 } else { &vtmp0 }; | |
324 | (mc_dsp.put_block_weighted[wmode - 1])(&mut frm.data[coff..], cstride, csrc, h / 2, cw); | |
325 | } | |
326 | }, | |
327 | (BMode::Bi, Some(buf0), Some(buf1)) => { // do both and avg | |
328 | mc_dsp.mc_blocks(&mut ytmp0, &mut utmp0, &mut vtmp0, buf0, xpos, ypos, w, h, mv0); | |
329 | mc_dsp.mc_blocks(&mut ytmp1, &mut utmp1, &mut vtmp1, buf1, xpos, ypos, w, h, mv1); | |
330 | ||
331 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
332 | let yw = match (weight0.luma_weighted, weight1.luma_weighted) { | |
333 | (true, true) => [weight0.luma_weight, weight0.luma_offset, weight1.luma_weight, weight1.luma_offset, weight0.luma_shift as i8], | |
334 | (true, false) => [weight0.luma_weight, weight0.luma_offset, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
335 | (false, true) => [1 << weight1.luma_shift, 0, weight1.luma_weight, weight1.luma_offset, weight1.luma_shift as i8], | |
336 | (false, false) => [1, 0, 1, 0, 0], | |
337 | }; | |
338 | let wmode = match w { | |
339 | 2 => 0, | |
340 | 4 => 1, | |
341 | 8 => 2, | |
342 | _ => 3, | |
343 | }; | |
344 | (mc_dsp.put_block_weighted2[wmode])(&mut frm.data[yoff..], frm.stride[0], &ytmp0, &ytmp1, h, yw); | |
345 | ||
346 | for chroma in 0..2 { | |
347 | let cstride = frm.stride[chroma + 1]; | |
348 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
349 | let cw0 = weight0.chroma_weight[chroma]; | |
350 | let co0 = weight0.chroma_offset[chroma]; | |
351 | let cw1 = weight1.chroma_weight[chroma]; | |
352 | let co1 = weight1.chroma_offset[chroma]; | |
353 | let cw = match (weight0.chroma_weighted, weight1.chroma_weighted) { | |
354 | (true, true) => [cw0, co0, cw1, co1, weight0.luma_shift as i8], | |
355 | (true, false) => [cw0, co0, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
356 | (false, true) => [1 << weight1.luma_shift, 0, cw1, co1, weight1.luma_shift as i8], | |
357 | (false, false) => [1, 0, 1, 0, 0], | |
358 | }; | |
359 | let csrc0 = if chroma == 0 { &utmp0 } else { &vtmp0 }; | |
360 | let csrc1 = if chroma == 0 { &utmp1 } else { &vtmp1 }; | |
361 | (mc_dsp.put_block_weighted2[wmode - 1])(&mut frm.data[coff..], cstride, csrc0, csrc1, h / 2, cw); | |
362 | } | |
363 | }, | |
364 | _ => { | |
365 | mc_dsp.gray_block(frm, xpos, ypos, w, h); | |
366 | }, | |
367 | }; | |
368 | } | |
369 | } | |
370 | ||
371 | fn get_weights(slice_hdr: &SliceHeader, frame_refs: &FrameRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) { | |
372 | let idx_l0 = ref_l0.index(); | |
373 | let idx_l1 = ref_l1.index(); | |
374 | if mode != BMode::Bi || weight_mode != 2 { | |
375 | (slice_hdr.get_weight(0, idx_l0), slice_hdr.get_weight(1, idx_l1)) | |
376 | } 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)) { | |
377 | let r0_poc = pic0.full_id as u16; | |
378 | let r1_poc = pic1.full_id as u16; | |
379 | let cur_id = frame_refs.cur_id as u16; | |
380 | if (r0_poc == r1_poc) || pic0.long_term.is_some() || pic1.long_term.is_some() { | |
381 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
382 | } | |
383 | ||
384 | let td = (i32::from(r1_poc) - i32::from(r0_poc)).max(-128).min(127); | |
385 | let tx = (16384 + (td / 2).abs()) / td; | |
386 | let tb = (i32::from(cur_id) - i32::from(r0_poc)).max(-128).min(127); | |
387 | let scale = ((tb * tx + 32) >> 6).max(-1024).min(1023); | |
388 | if scale == 128 || (scale >> 2) < -64 || (scale >> 2) > 128 { | |
389 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
390 | } | |
391 | let w1 = (scale >> 2) as i8; | |
392 | let w0 = 64 - w1; | |
393 | ||
394 | let weight0 = WeightInfo { | |
395 | luma_weighted: true, | |
396 | luma_weight: w0, | |
397 | luma_offset: 0, | |
398 | luma_shift: 5, | |
399 | chroma_weighted: true, | |
400 | chroma_weight: [w0; 2], | |
401 | chroma_offset: [0; 2], | |
402 | chroma_shift: 5, | |
403 | }; | |
404 | let weight1 = WeightInfo { | |
405 | luma_weighted: true, | |
406 | luma_weight: w1, | |
407 | luma_offset: 0, | |
408 | luma_shift: 5, | |
409 | chroma_weighted: true, | |
410 | chroma_weight: [w1; 2], | |
411 | chroma_offset: [0; 2], | |
412 | chroma_shift: 5, | |
413 | }; | |
414 | ||
415 | (weight0, weight1) | |
416 | } else { | |
417 | (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO) | |
418 | } | |
419 | } | |
420 | ||
421 | pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &FrameRefs, mc_dsp: &mut H264MC, weight_mode: u8) { | |
422 | let xpos = sstate.mb_x * 16; | |
423 | let ypos = sstate.mb_y * 16; | |
424 | ||
425 | match mb_info.mb_type { | |
426 | MBType::Intra16x16(_, _, _) => { | |
427 | pred_intra(frm, sstate, mb_info); | |
428 | }, | |
429 | MBType::Intra4x4 | MBType::Intra8x8 => { | |
430 | pred_intra(frm, sstate, mb_info); | |
431 | }, | |
432 | MBType::PCM => {}, | |
433 | MBType::PSkip => { | |
434 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
435 | let rpic = frame_refs.select_ref_pic(0, 0); | |
436 | let weight = &slice_hdr.get_weight(0, 0); | |
437 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
438 | }, | |
439 | MBType::P16x16 => { | |
440 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
441 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
442 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
443 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight, mc_dsp); | |
444 | }, | |
445 | MBType::P16x8 | MBType::P8x16 => { | |
446 | let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 { | |
447 | (16, 8, 0, 8) | |
448 | } else { | |
449 | (8, 16, 8, 0) | |
450 | }; | |
451 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
452 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
453 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
454 | do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight, mc_dsp); | |
455 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
456 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index()); | |
457 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index()); | |
458 | do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight, mc_dsp); | |
459 | }, | |
460 | MBType::P8x8 | MBType::P8x8Ref0 => { | |
461 | for part in 0..4 { | |
462 | let bx = (part & 1) * 8; | |
463 | let by = (part & 2) * 4; | |
464 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
465 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
466 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index()); | |
467 | ||
468 | match mb_info.sub_mb_type[part] { | |
469 | SubMBType::P8x8 => { | |
470 | do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight, mc_dsp); | |
471 | }, | |
472 | SubMBType::P8x4 => { | |
473 | do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic.clone(), weight, mc_dsp); | |
474 | let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0]; | |
475 | do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight, mc_dsp); | |
476 | }, | |
477 | SubMBType::P4x8 => { | |
478 | do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic.clone(), weight, mc_dsp); | |
479 | let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0]; | |
480 | do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight, mc_dsp); | |
481 | }, | |
482 | SubMBType::P4x4 => { | |
483 | for sb_no in 0..4 { | |
484 | let sxpos = xpos + bx + (sb_no & 1) * 4; | |
485 | let sypos = ypos + by + (sb_no & 2) * 2; | |
486 | let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4; | |
487 | let mv = sstate.get_cur_blk4(sblk_no).mv[0]; | |
488 | do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic.clone(), weight, mc_dsp); | |
489 | } | |
490 | }, | |
491 | _ => unreachable!(), | |
492 | }; | |
493 | } | |
494 | }, | |
495 | MBType::B16x16(mode) => { | |
496 | let mv0 = sstate.get_cur_blk4(0).mv[0]; | |
497 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
498 | let mv1 = sstate.get_cur_blk4(0).mv[1]; | |
499 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index()); | |
500 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]); | |
501 | do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
502 | }, | |
503 | MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { | |
504 | let (pw, ph) = mb_info.mb_type.size(); | |
505 | let (px, py) = (pw & 8, ph & 8); | |
506 | let modes = [mode0, mode1]; | |
507 | let (mut bx, mut by) = (0, 0); | |
508 | for part in 0..2 { | |
509 | let blk = if part == 0 { 0 } else { (px / 4) + py }; | |
510 | let mv0 = sstate.get_cur_blk4(blk).mv[0]; | |
511 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
512 | let mv1 = sstate.get_cur_blk4(blk).mv[1]; | |
513 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index()); | |
514 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]); | |
515 | do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, mc_dsp); | |
516 | bx += px; | |
517 | by += py; | |
518 | } | |
519 | }, | |
520 | MBType::Direct | MBType::BSkip => { | |
521 | let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type; | |
522 | let is_16x16 = colo_mb_type.is_16x16_ref(); | |
523 | ||
524 | if is_16x16 { | |
525 | let mv = sstate.get_cur_blk4(0).mv; | |
526 | let ref_idx = sstate.get_cur_blk8(0).ref_idx; | |
527 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
528 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
529 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
530 | do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
531 | } else { | |
532 | for blk4 in 0..16 { | |
533 | let mv = sstate.get_cur_blk4(blk4).mv; | |
534 | let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx; | |
535 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
536 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
537 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
538 | 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); | |
539 | } | |
540 | } | |
541 | sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); }); | |
542 | }, | |
543 | MBType::B8x8 => { | |
544 | for part in 0..4 { | |
545 | let ridx = sstate.get_cur_blk8(part).ref_idx; | |
546 | let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index()); | |
547 | let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index()); | |
548 | let subtype = mb_info.sub_mb_type[part]; | |
549 | let blk8 = (part & 1) * 2 + (part & 2) * 4; | |
550 | let mut bx = (part & 1) * 8; | |
551 | let mut by = (part & 2) * 4; | |
552 | match subtype { | |
553 | SubMBType::Direct8x8 => { | |
554 | for blk in 0..4 { | |
555 | let mv = sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv; | |
556 | let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx; | |
557 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
558 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
559 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
560 | do_b_mc(frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
561 | bx += 4; | |
562 | if blk == 1 { | |
563 | bx -= 8; | |
564 | by += 4; | |
565 | } | |
566 | } | |
567 | sstate.get_cur_blk8(part).ref_idx[0].set_direct(); | |
568 | sstate.get_cur_blk8(part).ref_idx[1].set_direct(); | |
569 | }, | |
570 | SubMBType::B8x8(mode) => { | |
571 | let mv = sstate.get_cur_blk4(blk8).mv; | |
572 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
573 | do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, mc_dsp); | |
574 | }, | |
575 | SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => { | |
576 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
577 | let (pw, ph) = subtype.size(); | |
578 | let mv = sstate.get_cur_blk4(blk8).mv; | |
579 | do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp); | |
580 | let addr2 = blk8 + (pw & 4) / 4 + (ph & 4); | |
581 | let mv = sstate.get_cur_blk4(addr2).mv; | |
582 | 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); | |
583 | }, | |
584 | SubMBType::B4x4(mode) => { | |
585 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
586 | for i in 0..4 { | |
587 | let addr2 = blk8 + (i & 1) + (i & 2) * 2; | |
588 | let mv = sstate.get_cur_blk4(addr2).mv; | |
589 | do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, mc_dsp); | |
590 | bx += 4; | |
591 | if i == 1 { | |
592 | bx -= 8; | |
593 | by += 4; | |
594 | } | |
595 | } | |
596 | }, | |
597 | _ => unreachable!(), | |
598 | }; | |
599 | } | |
600 | }, | |
601 | }; | |
602 | if !mb_info.mb_type.is_skip() { | |
603 | if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 { | |
604 | add_luma(frm, sstate, mb_info); | |
605 | } | |
606 | add_chroma(frm, sstate, mb_info); | |
607 | } | |
608 | } |