]>
Commit | Line | Data |
---|---|---|
495b7ec0 KS |
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) { | |
207 | if let Some(buf) = ref_pic { | |
208 | if !weight.is_weighted() { | |
209 | 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_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 | put_block_weighted(&mut frm.data[yoff..], frm.stride[0], &ytmp, w, h, yw); | |
223 | ||
224 | for chroma in 0..2 { | |
225 | let cstride = frm.stride[chroma + 1]; | |
226 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
227 | let cw = if weight.chroma_weighted { | |
228 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
229 | } else { | |
230 | [1, 0, 0] | |
231 | }; | |
232 | let csrc = if chroma == 0 { &utmp } else { &vtmp }; | |
233 | put_block_weighted(&mut frm.data[coff..], cstride, csrc, w / 2, h / 2, cw); | |
234 | } | |
235 | } | |
236 | } else { | |
237 | gray_block(frm, xpos, ypos, w, h); | |
238 | } | |
239 | } | |
240 | ||
241 | 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, avg_buf: &mut NAVideoBufferRef<u8>) { | |
242 | let do_weight = match (mode, weight0.is_weighted(), weight1.is_weighted()) { | |
243 | (BMode::L0, true, _) => true, | |
244 | (BMode::L1, _, true) => true, | |
245 | (BMode::Bi, true, true) => true, | |
246 | _ => false, | |
247 | }; | |
248 | if !do_weight { | |
249 | match mode { | |
250 | BMode::L0 => { | |
251 | if let Some(buf) = ref_pic0 { | |
252 | do_mc(frm, buf, xpos, ypos, w, h, mv0); | |
253 | } else { | |
254 | gray_block(frm, xpos, ypos, w, h); | |
255 | } | |
256 | }, | |
257 | BMode::L1 => { | |
258 | if let Some(buf) = ref_pic1 { | |
259 | do_mc(frm, buf, xpos, ypos, w, h, mv1); | |
260 | } else { | |
261 | gray_block(frm, xpos, ypos, w, h); | |
262 | } | |
263 | }, | |
264 | BMode::Bi => { | |
265 | match (ref_pic0, ref_pic1) { | |
266 | (Some(buf0), Some(buf1)) => { | |
267 | do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
268 | do_mc_avg(frm, buf1, xpos, ypos, w, h, mv1, avg_buf); | |
269 | }, | |
270 | (Some(buf0), None) => { | |
271 | do_mc(frm, buf0, xpos, ypos, w, h, mv0); | |
272 | }, | |
273 | (None, Some(buf1)) => { | |
274 | do_mc(frm, buf1, xpos, ypos, w, h, mv1); | |
275 | }, | |
276 | (None, None) => { | |
277 | gray_block(frm, xpos, ypos, w, h); | |
278 | }, | |
279 | }; | |
280 | }, | |
281 | }; | |
282 | } else { | |
283 | let mut ytmp0 = [0x80; 16 * 16]; | |
284 | let mut utmp0 = [0x80; 16 * 16]; | |
285 | let mut vtmp0 = [0x80; 16 * 16]; | |
286 | let mut ytmp1 = [0x80; 16 * 16]; | |
287 | let mut utmp1 = [0x80; 16 * 16]; | |
288 | let mut vtmp1 = [0x80; 16 * 16]; | |
289 | match (mode, ref_pic0, ref_pic1) { | |
290 | (BMode::L0, Some(buf), _) | (BMode::L1, _, Some(buf)) => { | |
291 | let (mv, weight) = if mode == BMode::L0 { (mv0, weight0) } else { (mv1, weight1) }; | |
292 | mc_blocks(&mut ytmp0, &mut utmp0, &mut vtmp0, buf, xpos, ypos, w, h, mv); | |
293 | ||
294 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
295 | let yw = if weight.luma_weighted { | |
296 | [weight.luma_weight, weight.luma_offset, weight.luma_shift as i8] | |
297 | } else { | |
298 | [1, 0, 0] | |
299 | }; | |
300 | put_block_weighted(&mut frm.data[yoff..], frm.stride[0], &ytmp0, w, h, yw); | |
301 | ||
302 | for chroma in 0..2 { | |
303 | let cstride = frm.stride[chroma + 1]; | |
304 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
305 | let cw = if weight.chroma_weighted { | |
306 | [weight.chroma_weight[chroma], weight.chroma_offset[chroma], weight.chroma_shift as i8] | |
307 | } else { | |
308 | [1, 0, 0] | |
309 | }; | |
310 | let csrc = if chroma == 0 { &utmp0 } else { &vtmp0 }; | |
311 | put_block_weighted(&mut frm.data[coff..], cstride, csrc, w / 2, h / 2, cw); | |
312 | } | |
313 | }, | |
314 | (BMode::Bi, Some(buf0), Some(buf1)) => { // do both and avg | |
315 | mc_blocks(&mut ytmp0, &mut utmp0, &mut vtmp0, buf0, xpos, ypos, w, h, mv0); | |
316 | mc_blocks(&mut ytmp1, &mut utmp1, &mut vtmp1, buf1, xpos, ypos, w, h, mv1); | |
317 | ||
318 | let yoff = frm.offset[0] + xpos + ypos * frm.stride[0]; | |
319 | let yw = match (weight0.luma_weighted, weight1.luma_weighted) { | |
320 | (true, true) => [weight0.luma_weight, weight0.luma_offset, weight1.luma_weight, weight1.luma_offset, weight0.luma_shift as i8], | |
321 | (true, false) => [weight0.luma_weight, weight0.luma_offset, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
322 | (false, true) => [1 << weight1.luma_shift, 0, weight1.luma_weight, weight1.luma_offset, weight1.luma_shift as i8], | |
323 | (false, false) => [1, 0, 1, 0, 0], | |
324 | }; | |
325 | put_block_weighted2(&mut frm.data[yoff..], frm.stride[0], &ytmp0, &ytmp1, w, h, yw); | |
326 | ||
327 | for chroma in 0..2 { | |
328 | let cstride = frm.stride[chroma + 1]; | |
329 | let coff = frm.offset[chroma + 1] + xpos / 2 + ypos / 2 * cstride; | |
330 | let cw0 = weight0.chroma_weight[chroma]; | |
331 | let co0 = weight0.chroma_offset[chroma]; | |
332 | let cw1 = weight1.chroma_weight[chroma]; | |
333 | let co1 = weight1.chroma_offset[chroma]; | |
334 | let cw = match (weight0.chroma_weighted, weight1.chroma_weighted) { | |
335 | (true, true) => [cw0, co0, cw1, co1, weight0.luma_shift as i8], | |
336 | (true, false) => [cw0, co0, 1 << weight0.luma_shift, 0, weight0.luma_shift as i8], | |
337 | (false, true) => [1 << weight1.luma_shift, 0, cw1, co1, weight1.luma_shift as i8], | |
338 | (false, false) => [1, 0, 1, 0, 0], | |
339 | }; | |
340 | let csrc0 = if chroma == 0 { &utmp0 } else { &vtmp0 }; | |
341 | let csrc1 = if chroma == 0 { &utmp1 } else { &vtmp1 }; | |
342 | put_block_weighted2(&mut frm.data[coff..], cstride, csrc0, csrc1, w / 2, h / 2, cw); | |
343 | } | |
344 | }, | |
345 | _ => { | |
346 | gray_block(frm, xpos, ypos, w, h); | |
347 | }, | |
348 | }; | |
349 | } | |
350 | } | |
351 | ||
352 | fn get_weights(slice_hdr: &SliceHeader, frame_refs: &FrameRefs, mode: BMode, weight_mode: u8, ref_l0: PicRef, ref_l1: PicRef) -> (WeightInfo, WeightInfo) { | |
353 | let idx_l0 = ref_l0.index(); | |
354 | let idx_l1 = ref_l1.index(); | |
355 | if mode != BMode::Bi || weight_mode != 2 { | |
356 | (slice_hdr.get_weight(0, idx_l0), slice_hdr.get_weight(1, idx_l1)) | |
357 | } 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)) { | |
358 | let r0_poc = pic0.full_id as u16; | |
359 | let r1_poc = pic1.full_id as u16; | |
360 | let cur_id = frame_refs.cur_id as u16; | |
361 | if (r0_poc == r1_poc) || pic0.long_term.is_some() || pic1.long_term.is_some() { | |
362 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
363 | } | |
364 | ||
365 | let td = (i32::from(r1_poc) - i32::from(r0_poc)).max(-128).min(127); | |
366 | let tx = (16384 + (td / 2).abs()) / td; | |
367 | let tb = (i32::from(cur_id) - i32::from(r0_poc)).max(-128).min(127); | |
368 | let scale = ((tb * tx + 32) >> 6).max(-1024).min(1023); | |
369 | if scale == 128 || (scale >> 2) < -64 || (scale >> 2) > 128 { | |
370 | return (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO); | |
371 | } | |
372 | let w1 = (scale >> 2) as i8; | |
373 | let w0 = 64 - w1; | |
374 | ||
375 | let weight0 = WeightInfo { | |
376 | luma_weighted: true, | |
377 | luma_weight: w0, | |
378 | luma_offset: 0, | |
379 | luma_shift: 5, | |
380 | chroma_weighted: true, | |
381 | chroma_weight: [w0; 2], | |
382 | chroma_offset: [0; 2], | |
383 | chroma_shift: 5, | |
384 | }; | |
385 | let weight1 = WeightInfo { | |
386 | luma_weighted: true, | |
387 | luma_weight: w1, | |
388 | luma_offset: 0, | |
389 | luma_shift: 5, | |
390 | chroma_weighted: true, | |
391 | chroma_weight: [w1; 2], | |
392 | chroma_offset: [0; 2], | |
393 | chroma_shift: 5, | |
394 | }; | |
395 | ||
396 | (weight0, weight1) | |
397 | } else { | |
398 | (DEF_WEIGHT_INFO, DEF_WEIGHT_INFO) | |
399 | } | |
400 | } | |
401 | ||
402 | pub fn recon_mb(frm: &mut NASimpleVideoFrame<u8>, slice_hdr: &SliceHeader, mb_info: &CurrentMBInfo, sstate: &mut SliceState, frame_refs: &FrameRefs, avg_buf: &mut NAVideoBufferRef<u8>, weight_mode: u8) { | |
403 | let xpos = sstate.mb_x * 16; | |
404 | let ypos = sstate.mb_y * 16; | |
405 | ||
406 | match mb_info.mb_type { | |
407 | MBType::Intra16x16(_, _, _) => { | |
408 | pred_intra(frm, &sstate, &mb_info); | |
409 | }, | |
410 | MBType::Intra4x4 | MBType::Intra8x8 => { | |
411 | pred_intra(frm, &sstate, &mb_info); | |
412 | }, | |
413 | MBType::PCM => {}, | |
414 | MBType::PSkip => { | |
415 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
416 | let rpic = frame_refs.select_ref_pic(0, 0); | |
417 | let weight = &slice_hdr.get_weight(0, 0); | |
418 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight); | |
419 | }, | |
420 | MBType::P16x16 => { | |
421 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
422 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
423 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
424 | do_p_mc(frm, xpos, ypos, 16, 16, mv, rpic, weight); | |
425 | }, | |
426 | MBType::P16x8 | MBType::P8x16 => { | |
427 | let (bw, bh, bx, by) = if mb_info.mb_type == MBType::P16x8 { | |
428 | (16, 8, 0, 8) | |
429 | } else { | |
430 | (8, 16, 8, 0) | |
431 | }; | |
432 | let mv = sstate.get_cur_blk4(0).mv[0]; | |
433 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
434 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[0].index()); | |
435 | do_p_mc(frm, xpos, ypos, bw, bh, mv, rpic, weight); | |
436 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
437 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[1].index()); | |
438 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[1].index()); | |
439 | do_p_mc(frm, xpos + bx, ypos + by, bw, bh, mv, rpic, weight); | |
440 | }, | |
441 | MBType::P8x8 | MBType::P8x8Ref0 => { | |
442 | for part in 0..4 { | |
443 | let bx = (part & 1) * 8; | |
444 | let by = (part & 2) * 4; | |
445 | let mv = sstate.get_cur_blk4(bx / 4 + by).mv[0]; | |
446 | let rpic = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
447 | let weight = &slice_hdr.get_weight(0, mb_info.ref_l0[part].index()); | |
448 | ||
449 | match mb_info.sub_mb_type[part] { | |
450 | SubMBType::P8x8 => { | |
451 | do_p_mc(frm, xpos + bx, ypos + by, 8, 8, mv, rpic, weight); | |
452 | }, | |
453 | SubMBType::P8x4 => { | |
454 | do_p_mc(frm, xpos + bx, ypos + by, 8, 4, mv, rpic.clone(), weight); | |
455 | let mv = sstate.get_cur_blk4(bx / 4 + by + 4).mv[0]; | |
456 | do_p_mc(frm, xpos + bx, ypos + by + 4, 8, 4, mv, rpic, weight); | |
457 | }, | |
458 | SubMBType::P4x8 => { | |
459 | do_p_mc(frm, xpos + bx, ypos + by, 4, 8, mv, rpic.clone(), weight); | |
460 | let mv = sstate.get_cur_blk4(bx / 4 + by + 1).mv[0]; | |
461 | do_p_mc(frm, xpos + bx + 4, ypos + by, 4, 8, mv, rpic, weight); | |
462 | }, | |
463 | SubMBType::P4x4 => { | |
464 | for sb_no in 0..4 { | |
465 | let sxpos = xpos + bx + (sb_no & 1) * 4; | |
466 | let sypos = ypos + by + (sb_no & 2) * 2; | |
467 | let sblk_no = (bx / 4 + (sb_no & 1)) + ((by / 4) + (sb_no >> 1)) * 4; | |
468 | let mv = sstate.get_cur_blk4(sblk_no).mv[0]; | |
469 | do_p_mc(frm, sxpos, sypos, 4, 4, mv, rpic.clone(), weight); | |
470 | } | |
471 | }, | |
472 | _ => unreachable!(), | |
473 | }; | |
474 | } | |
475 | }, | |
476 | MBType::B16x16(mode) => { | |
477 | let mv0 = sstate.get_cur_blk4(0).mv[0]; | |
478 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[0].index()); | |
479 | let mv1 = sstate.get_cur_blk4(0).mv[1]; | |
480 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[0].index()); | |
481 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, mb_info.ref_l0[0], mb_info.ref_l1[0]); | |
482 | do_b_mc(frm, mode, xpos, ypos, 16, 16, mv0, rpic0, &weight0, mv1, rpic1, &weight1, avg_buf); | |
483 | }, | |
484 | MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { | |
485 | let (pw, ph) = mb_info.mb_type.size(); | |
486 | let (px, py) = (pw & 8, ph & 8); | |
487 | let modes = [mode0, mode1]; | |
488 | let (mut bx, mut by) = (0, 0); | |
489 | for part in 0..2 { | |
490 | let blk = if part == 0 { 0 } else { (px / 4) + py }; | |
491 | let mv0 = sstate.get_cur_blk4(blk).mv[0]; | |
492 | let rpic0 = frame_refs.select_ref_pic(0, mb_info.ref_l0[part].index()); | |
493 | let mv1 = sstate.get_cur_blk4(blk).mv[1]; | |
494 | let rpic1 = frame_refs.select_ref_pic(1, mb_info.ref_l1[part].index()); | |
495 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, modes[part], weight_mode, mb_info.ref_l0[part], mb_info.ref_l1[part]); | |
496 | do_b_mc(frm, modes[part], xpos + bx, ypos + by, pw, ph, mv0, rpic0, &weight0, mv1, rpic1, &weight1, avg_buf); | |
497 | bx += px; | |
498 | by += py; | |
499 | } | |
500 | }, | |
501 | MBType::Direct | MBType::BSkip => { | |
502 | let colo_mb_type = frame_refs.get_colocated_info(sstate.mb_x, sstate.mb_y).0.mb_type; | |
503 | let is_16x16 = colo_mb_type.is_16x16_ref(); | |
504 | ||
505 | if is_16x16 { | |
506 | let mv = sstate.get_cur_blk4(0).mv; | |
507 | let ref_idx = sstate.get_cur_blk8(0).ref_idx; | |
508 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
509 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
510 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
511 | do_b_mc(frm, BMode::Bi, xpos, ypos, 16, 16, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, avg_buf); | |
512 | } else { | |
513 | for blk4 in 0..16 { | |
514 | let mv = sstate.get_cur_blk4(blk4).mv; | |
515 | let ref_idx = sstate.get_cur_blk8(blk4_to_blk8(blk4)).ref_idx; | |
516 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
517 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
518 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
519 | do_b_mc(frm, BMode::Bi, xpos + (blk4 & 3) * 4, ypos + (blk4 >> 2) * 4, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, avg_buf); | |
520 | } | |
521 | } | |
522 | sstate.apply_to_blk8(|blk8| { blk8.ref_idx[0].set_direct(); blk8.ref_idx[1].set_direct(); }); | |
523 | }, | |
524 | MBType::B8x8 => { | |
525 | for part in 0..4 { | |
526 | let ridx = sstate.get_cur_blk8(part).ref_idx; | |
527 | let rpic0 = frame_refs.select_ref_pic(0, ridx[0].index()); | |
528 | let rpic1 = frame_refs.select_ref_pic(1, ridx[1].index()); | |
529 | let subtype = mb_info.sub_mb_type[part]; | |
530 | let blk8 = (part & 1) * 2 + (part & 2) * 4; | |
531 | let mut bx = (part & 1) * 8; | |
532 | let mut by = (part & 2) * 4; | |
533 | match subtype { | |
534 | SubMBType::Direct8x8 => { | |
535 | for blk in 0..4 { | |
536 | let mv = sstate.get_cur_blk4(bx / 4 + (by / 4) * 4).mv; | |
537 | let ref_idx = sstate.get_cur_blk8(bx / 8 + (by / 8) * 2).ref_idx; | |
538 | let rpic0 = frame_refs.select_ref_pic(0, ref_idx[0].index()); | |
539 | let rpic1 = frame_refs.select_ref_pic(1, ref_idx[1].index()); | |
540 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, BMode::Bi, weight_mode, ref_idx[0], ref_idx[1]); | |
541 | do_b_mc(frm, BMode::Bi, xpos + bx, ypos + by, 4, 4, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, avg_buf); | |
542 | bx += 4; | |
543 | if blk == 1 { | |
544 | bx -= 8; | |
545 | by += 4; | |
546 | } | |
547 | } | |
548 | sstate.get_cur_blk8(part).ref_idx[0].set_direct(); | |
549 | sstate.get_cur_blk8(part).ref_idx[1].set_direct(); | |
550 | }, | |
551 | SubMBType::B8x8(mode) => { | |
552 | let mv = sstate.get_cur_blk4(blk8).mv; | |
553 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
554 | do_b_mc(frm, mode, xpos + bx, ypos + by, 8, 8, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, avg_buf); | |
555 | }, | |
556 | SubMBType::B8x4(mode) | SubMBType::B4x8(mode) => { | |
557 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
558 | let (pw, ph) = subtype.size(); | |
559 | let mv = sstate.get_cur_blk4(blk8).mv; | |
560 | do_b_mc(frm, mode, xpos + bx, ypos + by, pw, ph, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, avg_buf); | |
561 | let addr2 = blk8 + (pw & 4) / 4 + (ph & 4); | |
562 | let mv = sstate.get_cur_blk4(addr2).mv; | |
563 | do_b_mc(frm, mode, xpos + bx + (pw & 4), ypos + by + (ph & 4), pw, ph, mv[0], rpic0, &weight0, mv[1], rpic1, &weight1, avg_buf); | |
564 | }, | |
565 | SubMBType::B4x4(mode) => { | |
566 | let (weight0, weight1) = get_weights(slice_hdr, frame_refs, mode, weight_mode, ridx[0], ridx[1]); | |
567 | for i in 0..4 { | |
568 | let addr2 = blk8 + (i & 1) + (i & 2) * 2; | |
569 | let mv = sstate.get_cur_blk4(addr2).mv; | |
570 | do_b_mc(frm, mode, xpos + bx, ypos + by, 4, 4, mv[0], rpic0.clone(), &weight0, mv[1], rpic1.clone(), &weight1, avg_buf); | |
571 | bx += 4; | |
572 | if i == 1 { | |
573 | bx -= 8; | |
574 | by += 4; | |
575 | } | |
576 | } | |
577 | }, | |
578 | _ => unreachable!(), | |
579 | }; | |
580 | } | |
581 | }, | |
582 | }; | |
583 | if !mb_info.mb_type.is_skip() { | |
584 | if mb_info.mb_type != MBType::Intra4x4 && mb_info.mb_type != MBType::Intra8x8 { | |
585 | add_luma(frm, &sstate, &mb_info); | |
586 | } | |
587 | add_chroma(frm, &sstate, &mb_info); | |
588 | } | |
589 | } |