RealVideo 4 encoder
[nihav.git] / nihav-realmedia / src / codecs / rv40enc / dsp / ipred.rs
CommitLineData
4965a5e5
KS
1use super::super::types::{PredType8x8, PredType4x4};
2use super::RefMBData;
3
4#[derive(Default)]
5pub struct IntraPred16x16 {
6 pub top: [u8; 17],
7 pub left: [u8; 17],
8}
9
10impl IntraPred16x16 {
11 pub fn new() -> Self { Self::default() }
12 #[allow(clippy::many_single_char_names)]
13 pub fn apply16(&self, mode: PredType8x8, dst: &mut [u8], stride: usize) {
14 match mode {
15 PredType8x8::DC => {
16 let sumt = self.top[1..].iter().fold(0u32, |acc, &x| acc + u32::from(x));
17 let suml = self.left[1..].iter().fold(0u32, |acc, &x| acc + u32::from(x));
18 let dc = ((sumt + suml + 16) >> 5) as u8;
19 for line in dst.chunks_mut(stride).take(16) {
20 for dst in line[..16].iter_mut() {
21 *dst = dc;
22 }
23 }
24 },
25 PredType8x8::Hor => {
26 for (&left, line) in self.left[1..].iter().zip(dst.chunks_mut(stride)) {
27 for dst in line[..16].iter_mut() {
28 *dst = left;
29 }
30 }
31 },
32 PredType8x8::Ver => {
33 for line in dst.chunks_mut(stride).take(16) {
34 line[..16].copy_from_slice(&self.top[1..]);
35 }
36 },
37 PredType8x8::Plane => {
38 let top0 = &self.top[9..];
39 let top1 = &self.top[..8];
40 let h = top0.iter().zip(top1.iter().rev()).enumerate().fold(
41 0i32, |acc, (k, (&a, &b))| acc + ((k + 1) as i32) * (i32::from(a) - i32::from(b)));
42 let left0 = &self.left[9..];
43 let left1 = &self.left[..8];
44 let v = left0.iter().zip(left1.iter().rev()).enumerate().fold(
45 0i32, |acc, (k, (&a, &b))| acc + ((k + 1) as i32) * (i32::from(a) - i32::from(b)));
46 let b = (h + (h >> 2)) >> 4;
47 let c = (v + (v >> 2)) >> 4;
48 let mut a = 16 * (i32::from(self.left[16]) + i32::from(self.top[16])) + 16 - 7 * (b + c);
49
50 for line in dst.chunks_mut(stride).take(16) {
51 let mut oval = a;
52 for el in line[..16].iter_mut() {
53 *el = (oval >> 5).max(0).min(255) as u8;
54 oval += b;
55 }
56 a += c;
57 }
58 },
59 PredType8x8::LeftDC => {
60 let dc = ((self.left[1..].iter().fold(0u32, |acc, &x| acc + u32::from(x)) + 8) >> 4) as u8;
61 for line in dst.chunks_mut(stride).take(16) {
62 for dst in line[..16].iter_mut() {
63 *dst = dc;
64 }
65 }
66 },
67 PredType8x8::TopDC => {
68 let dc = ((self.top[1..].iter().fold(0u32, |acc, &x| acc + u32::from(x)) + 8) >> 4) as u8;
69 for line in dst.chunks_mut(stride).take(16) {
70 for dst in line[..16].iter_mut() {
71 *dst = dc;
72 }
73 }
74 },
75 PredType8x8::DC128 => {
76 for line in dst.chunks_mut(stride).take(16) {
77 for dst in line[..16].iter_mut() {
78 *dst = 128;
79 }
80 }
81 },
82 }
83 }
84 pub fn apply8(&self, mode: PredType8x8, dst: &mut [u8], stride: usize) {
85 match mode {
86 PredType8x8::DC | PredType8x8::Plane => {
87 let sumt = self.top[1..9].iter().fold(0u32, |acc, &x| acc + u32::from(x));
88 let suml = self.left[1..9].iter().fold(0u32, |acc, &x| acc + u32::from(x));
89 let dc = ((sumt + suml + 8) >> 4) as u8;
90 for line in dst.chunks_mut(stride).take(8) {
91 for dst in line[..8].iter_mut() {
92 *dst = dc;
93 }
94 }
95 },
96 PredType8x8::Hor => {
97 for (&left, line) in self.left[1..9].iter().zip(dst.chunks_mut(stride)) {
98 for dst in line[..8].iter_mut() {
99 *dst = left;
100 }
101 }
102 },
103 PredType8x8::Ver => {
104 for line in dst.chunks_mut(stride).take(8) {
105 line[..8].copy_from_slice(&self.top[1..9]);
106 }
107 },
108 PredType8x8::LeftDC => {
109 let dc = ((self.left[1..9].iter().fold(0u32, |acc, &x| acc + u32::from(x)) + 4) >> 3) as u8;
110 for line in dst.chunks_mut(stride).take(8) {
111 for dst in line[..8].iter_mut() {
112 *dst = dc;
113 }
114 }
115 },
116 PredType8x8::TopDC => {
117 let dc = ((self.top[1..9].iter().fold(0u32, |acc, &x| acc + u32::from(x)) + 4) >> 3) as u8;
118 for line in dst.chunks_mut(stride).take(8) {
119 for dst in line[..8].iter_mut() {
120 *dst = dc;
121 }
122 }
123 },
124 PredType8x8::DC128 => {
125 for line in dst.chunks_mut(stride).take(8) {
126 for dst in line[..8].iter_mut() {
127 *dst = 128;
128 }
129 }
130 },
131 }
132 }
133}
134
135#[derive(Default)]
136pub struct Intra4Pred {
137 pub top: [u8; 8],
138 pub left: [u8; 8],
139 pub tl: u8,
140}
141
142impl Intra4Pred {
143 pub fn new() -> Self { Self::default() }
144 fn load_left(&self) -> [u16; 8] {
145 let mut ret = [0; 8];
146 for (dst, &src) in ret.iter_mut().zip(self.left.iter()) {
147 *dst = u16::from(src);
148 }
149 ret
150 }
151 fn load_top(&self) -> [u16; 8] {
152 let mut ret = [0; 8];
153 for (dst, &src) in ret.iter_mut().zip(self.top.iter()) {
154 *dst = u16::from(src);
155 }
156 ret
157 }
158 fn load_left_and_top(&self) -> ([u16; 5], [u16; 5]) {
159 let mut left = [0; 5];
160 let mut top = [0; 5];
161 left[0] = u16::from(self.tl);
162 top[0] = u16::from(self.tl);
163 for (dst, &src) in left[1..].iter_mut().zip(self.left.iter()) {
164 *dst = u16::from(src);
165 }
166 for (dst, &src) in top[1..].iter_mut().zip(self.top.iter()) {
167 *dst = u16::from(src);
168 }
169 (left, top)
170 }
171 #[allow(clippy::many_single_char_names)]
172 pub fn apply(&self, ptype: PredType4x4, buf: &mut [u8], stride: usize) {
173 match ptype {
174 PredType4x4::DC => {
175 let dc_l = self.left[..4].iter().fold(0u32, |acc, &x| acc + u32::from(x));
176 let dc_t = self.top [..4].iter().fold(0u32, |acc, &x| acc + u32::from(x));
177 let dc = ((dc_t + dc_l + 4) >> 3) as u8;
178 for line in buf.chunks_mut(stride).take(4) {
179 for el in line[..4].iter_mut() {
180 *el = dc;
181 }
182 }
183 },
184 PredType4x4::LeftDC => {
185 let dc_l = self.left[..4].iter().fold(0u32, |acc, &x| acc + u32::from(x));
186 let dc = ((dc_l + 2) >> 2) as u8;
187 for line in buf.chunks_mut(stride).take(4) {
188 for el in line[..4].iter_mut() {
189 *el = dc;
190 }
191 }
192 },
193 PredType4x4::TopDC => {
194 let dc_t = self.top [..4].iter().fold(0u32, |acc, &x| acc + u32::from(x));
195 let dc = ((dc_t + 2) >> 2) as u8;
196 for line in buf.chunks_mut(stride).take(4) {
197 for el in line[..4].iter_mut() {
198 *el = dc;
199 }
200 }
201 },
202 PredType4x4::DC128 => {
203 for line in buf.chunks_mut(stride).take(4) {
204 for el in line[..4].iter_mut() {
205 *el = 128;
206 }
207 }
208 },
209 PredType4x4::Ver => {
210 for line in buf.chunks_mut(stride).take(4) {
211 line[..4].copy_from_slice(&self.top[..4]);
212 }
213 },
214 PredType4x4::Hor => {
215 for (&left, line) in self.left[..4].iter().zip(buf.chunks_mut(stride)) {
216 for dst in line[..4].iter_mut() {
217 *dst = left;
218 }
219 }
220 },
221 PredType4x4::DiagDownLeft => {
222 let l = self.load_left();
223 let t = self.load_top();
224 buf[0] = ((t[0] + t[2] + 2*t[1] + 2 + l[0] + l[2] + 2*l[1] + 2) >> 3) as u8;
225 let pix = ((t[1] + t[3] + 2*t[2] + 2 + l[1] + l[3] + 2*l[2] + 2) >> 3) as u8;
226 buf[1] = pix;
227 buf[stride] = pix;
228 let pix = ((t[2] + t[4] + 2*t[3] + 2 + l[2] + l[4] + 2*l[3] + 2) >> 3) as u8;
229 buf[2] = pix;
230 buf[1 + stride] = pix;
231 buf[2 * stride] = pix;
232 let pix = ((t[3] + t[5] + 2*t[4] + 2 + l[3] + l[5] + 2*l[4] + 2) >> 3) as u8;
233 buf[3] = pix;
234 buf[2 + stride] = pix;
235 buf[1 + 2 * stride] = pix;
236 buf[ 3 * stride] = pix;
237 let pix = ((t[4] + t[6] + 2*t[5] + 2 + l[4] + l[6] + 2*l[5] + 2) >> 3) as u8;
238 buf[3 + stride] = pix;
239 buf[2 + 2 * stride] = pix;
240 buf[1 + 3 * stride] = pix;
241 let pix = ((t[5] + t[7] + 2*t[6] + 2 + l[5] + l[7] + 2*l[6] + 2) >> 3) as u8;
242 buf[3 + 2 * stride] = pix;
243 buf[2 + 3 * stride] = pix;
244 buf[3 + 3 * stride] = ((t[6] + t[7] + 1 + l[6] + l[7] + 1) >> 2) as u8;
245 },
246 PredType4x4::DiagDownRight => {
247 let (l, t) = self.load_left_and_top();
248 for (j, line) in buf.chunks_mut(stride).take(4).enumerate() {
249 for i in 0..j {
250 line[i] = ((l[j - i - 1] + 2 * l[j - i] + l[j - i + 1] + 2) >> 2) as u8;
251 }
252 line[j] = ((l[1] + 2 * l[0] + t[1] + 2) >> 2) as u8;
253 for i in (j + 1)..4 {
254 line[i] = ((t[i - j - 1] + 2 * t[i - j] + t[i - j + 1] + 2) >> 2) as u8;
255 }
256 }
257 },
258 PredType4x4::VerRight => {
259 let (l, t) = self.load_left_and_top();
260 for (j, line) in buf.chunks_mut(stride).take(4).enumerate() {
261 for (i, pix) in line[..4].iter_mut().enumerate() {
262 let zvr = ((2 * i) as i8) - (j as i8);
263 *pix = if zvr >= 0 {
264 if (zvr & 1) == 0 {
265 (t[i - (j >> 1)] + t[i - (j >> 1) + 1] + 1) >> 1
266 } else {
267 (t[i - (j >> 1) - 1] + 2 * t[i - (j >> 1)] + t[i - (j >> 1) + 1] + 2) >> 2
268 }
269 } else {
270 if zvr == -1 {
271 (l[1] + 2 * l[0] + t[1] + 2) >> 2
272 } else {
273 (l[j] + 2 * l[j - 1] + l[j - 2] + 2) >> 2
274 }
275 } as u8;
276 }
277 }
278 },
279 PredType4x4::HorDown => {
280 let (l, t) = self.load_left_and_top();
281 for (j, line) in buf.chunks_mut(stride).take(4).enumerate() {
282 for (i, pix) in line[..4].iter_mut().enumerate() {
283 let zhd = ((2 * j) as i8) - (i as i8);
284 *pix = if zhd >= 0 {
285 if (zhd & 1) == 0 {
286 (l[j - (i >> 1)] + l[j - (i >> 1) + 1] + 1) >> 1
287 } else {
288 (l[j - (i >> 1) - 1] + 2 * l[j - (i >> 1)] + l[j - (i >> 1) + 1] + 2) >> 2
289 }
290 } else {
291 if zhd == -1 {
292 (l[1] + 2 * l[0] + t[1] + 2) >> 2
293 } else {
294 (t[i - 2] + 2 * t[i - 1] + t[i] + 2) >> 2
295 }
296 } as u8;
297 }
298 }
299 },
300 PredType4x4::VerLeft => {
301 let l = self.load_left();
302 let t = self.load_top();
303 buf[0] = ((2*t[0] + 2*t[1] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
304 let pix = ((t[1] + t[2] + 1) >> 1) as u8;
305 buf[1] = pix;
306 buf[2 * stride] = pix;
307 let pix = ((t[2] + t[3] + 1) >> 1) as u8;
308 buf[2] = pix;
309 buf[1 + 2 * stride] = pix;
310 let pix = ((t[3] + t[4] + 1) >> 1) as u8;
311 buf[3] = pix;
312 buf[2 + 2 * stride] = pix;
313 buf[3 + 2 * stride] = ((t[4] + t[5] + 1) >> 1) as u8;
314 buf[ stride] = ((t[0] + 2*t[1] + t[2] + l[2] + 2*l[3] + l[4] + 4) >> 3) as u8;
315 let pix = ((t[1] + 2*t[2] + t[3] + 2) >> 2) as u8;
316 buf[1 + stride] = pix;
317 buf[ 3 * stride] = pix;
318 let pix = ((t[2] + 2*t[3] + t[4] + 2) >> 2) as u8;
319 buf[2 + stride] = pix;
320 buf[1 + 3 * stride] = pix;
321 let pix = ((t[3] + 2*t[4] + t[5] + 2) >> 2) as u8;
322 buf[3 + stride] = pix;
323 buf[2 + 3 * stride] = pix;
324 buf[3 + 3 * stride] = ((t[4] + 2*t[5] + t[6] + 2) >> 2) as u8;
325 },
326 PredType4x4::HorUp => {
327 let l = self.load_left();
328 let t = self.load_top();
329 buf[0] = ((t[1] + 2*t[2] + t[3] + 2*l[0] + 2*l[1] + 4) >> 3) as u8;
330 buf[1] = ((t[2] + 2*t[3] + t[4] + l[0] + 2*l[1] + l[2] + 4) >> 3) as u8;
331 let pix = ((t[3] + 2*t[4] + t[5] + 2*l[1] + 2*l[2] + 4) >> 3) as u8;
332 buf[2] = pix;
333 buf[ stride] = pix;
334 let pix = ((t[4] + 2*t[5] + t[6] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
335 buf[3] = pix;
336 buf[1 + stride] = pix;
337 let pix = ((t[5] + 2*t[6] + t[7] + 2*l[2] + 2*l[3] + 4) >> 3) as u8;
338 buf[2 + stride] = pix;
339 buf[0 + 2 * stride] = pix;
340 let pix = ((t[6] + 3*t[7] + l[2] + 3*l[3] + 4) >> 3) as u8;
341 buf[3 + stride] = pix;
342 buf[1 + 2 * stride] = pix;
343 let pix = ((l[3] + 2*l[4] + l[5] + 2) >> 2) as u8;
344 buf[3 + 2 * stride] = pix;
345 buf[1 + 3 * stride] = pix;
346 let pix = ((t[6] + t[7] + l[3] + l[4] + 2) >> 2) as u8;
347 buf[0 + 3 * stride] = pix;
348 buf[2 + 2 * stride] = pix;
349 buf[2 + 3 * stride] = ((l[4] + l[5] + 1) >> 1) as u8;
350 buf[3 + 3 * stride] = ((l[4] + 2*l[5] + l[6] + 2) >> 2) as u8;
351 },
352 PredType4x4::DiagDownLeftNoDown => {
353 let l = self.load_left();
354 let t = self.load_top();
355 buf[0] = ((t[0] + t[2] + 2*t[1] + 2 + l[0] + l[2] + 2*l[1] + 2) >> 3) as u8;
356 let pix = ((t[1] + t[3] + 2*t[2] + 2 + l[1] + l[3] + 2*l[2] + 2) >> 3) as u8;
357 buf[1] = pix;
358 buf[0 + stride] = pix;
359 let pix = ((t[2] + t[4] + 2*t[3] + 2 + l[2] + 3*l[3] + 2) >> 3) as u8;
360 buf[2] = pix;
361 buf[1 + stride] = pix;
362 buf[0 + 2 * stride] = pix;
363 let pix = ((t[3] + t[5] + 2*t[4] + 2 + l[3]*4 + 2) >> 3) as u8;
364 buf[3] = pix;
365 buf[2 + stride] = pix;
366 buf[1 + 2 * stride] = pix;
367 buf[0 + 3 * stride] = pix;
368 let pix = ((t[4] + t[6] + 2*t[5] + 2 + l[3]*4 + 2) >> 3) as u8;
369 buf[3 + stride] = pix;
370 buf[2 + 2 * stride] = pix;
371 buf[1 + 3 * stride] = pix;
372 let pix = ((t[5] + t[7] + 2*t[6] + 2 + l[3]*4 + 2) >> 3) as u8;
373 buf[3 + 2 * stride] = pix;
374 buf[2 + 3 * stride] = pix;
375 buf[3 + 3 * stride] = ((t[6] + t[7] + 1 + 2*l[3] + 1) >> 2) as u8;
376 },
377 PredType4x4::HorUpNoDown => {
378 let l = self.load_left();
379 let t = self.load_top();
380 buf[0] = ((t[1] + 2*t[2] + t[3] + 2*l[0] + 2*l[1] + 4) >> 3) as u8;
381 buf[1] = ((t[2] + 2*t[3] + t[4] + l[0] + 2*l[1] + l[2] + 4) >> 3) as u8;
382 let pix = ((t[3] + 2*t[4] + t[5] + 2*l[1] + 2*l[2] + 4) >> 3) as u8;
383 buf[2] = pix;
384 buf[ stride] = pix;
385 let pix = ((t[4] + 2*t[5] + t[6] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
386 buf[3] = pix;
387 buf[1 + stride] = pix;
388 let pix = ((t[5] + 2*t[6] + t[7] + 2*l[2] + 2*l[3] + 4) >> 3) as u8;
389 buf[2 + stride] = pix;
390 buf[ 2 * stride] = pix;
391 let pix = ((t[6] + 3*t[7] + l[2] + 3*l[3] + 4) >> 3) as u8;
392 buf[3 + stride] = pix;
393 buf[1 + 2 * stride] = pix;
394 buf[3 + 2 * stride] = l[3] as u8;
395 buf[1 + 3 * stride] = l[3] as u8;
396 let pix = ((t[6] + t[7] + 2*l[3] + 2) >> 2) as u8;
397 buf[0 + 3 * stride] = pix;
398 buf[2 + 2 * stride] = pix;
399 buf[2 + 3 * stride] = l[3] as u8;
400 buf[3 + 3 * stride] = l[3] as u8;
401 },
402 PredType4x4::VerLeftNoDown => {
403 let l = [u16::from(self.left[0]), u16::from(self.left[1]), u16::from(self.left[2]), u16::from(self.left[3]), u16::from(self.left[3])];
404 let t = self.load_top();
405 buf[0] = ((2*t[0] + 2*t[1] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
406 let pix = ((t[1] + t[2] + 1) >> 1) as u8;
407 buf[1] = pix;
408 buf[ 2 * stride] = pix;
409 let pix = ((t[2] + t[3] + 1) >> 1) as u8;
410 buf[2] = pix;
411 buf[1 + 2 * stride] = pix;
412 let pix = ((t[3] + t[4] + 1) >> 1) as u8;
413 buf[3] = pix;
414 buf[2 + 2 * stride] = pix;
415 buf[3 + 2 * stride] = ((t[4] + t[5] + 1) >> 1) as u8;
416 buf[ stride] = ((t[0] + 2*t[1] + t[2] + l[2] + 2*l[3] + l[4] + 4) >> 3) as u8;
417 let pix = ((t[1] + 2*t[2] + t[3] + 2) >> 2) as u8;
418 buf[1 + stride] = pix;
419 buf[ 3 * stride] = pix;
420 let pix = ((t[2] + 2*t[3] + t[4] + 2) >> 2) as u8;
421 buf[2 + stride] = pix;
422 buf[1 + 3 * stride] = pix;
423 let pix = ((t[3] + 2*t[4] + t[5] + 2) >> 2) as u8;
424 buf[3 + stride] = pix;
425 buf[2 + 3 * stride] = pix;
426 buf[3 + 3 * stride] = ((t[4] + 2*t[5] + t[6] + 2) >> 2) as u8;
427 },
428 }
429 }
430}
431
432pub struct BlockIntra4Pred {
433 pub ipred_y: Intra4Pred,
434 pub ipred_u: Intra4Pred,
435 pub ipred_v: Intra4Pred,
436 pub top_y: [u8; 21],
437 pub top_u: [u8; 13],
438 pub top_v: [u8; 13],
439 pub left_y: [u8; 16],
440 pub left_u: [u8; 8],
441 pub left_v: [u8; 8],
442 pub has_l: bool,
443}
444
445impl BlockIntra4Pred {
446 pub fn new(src_y: &IntraPred16x16, src_u: &IntraPred16x16, src_v: &IntraPred16x16, tr_y: [u8; 4], tr_u: [u8; 4], tr_v: [u8; 4], has_l: bool) -> Self {
447 let mut top_y = [0; 21];
448 top_y[..17].copy_from_slice(&src_y.top);
449 top_y[17..].copy_from_slice(&tr_y);
450 let mut top_u = [0; 13];
451 top_u[..9].copy_from_slice(&src_u.top[..9]);
452 top_u[9..].copy_from_slice(&tr_u);
453 let mut top_v = [0; 13];
454 top_v[..9].copy_from_slice(&src_v.top[..9]);
455 top_v[9..].copy_from_slice(&tr_v);
456 let mut left_y = [0; 16];
457 left_y.copy_from_slice(&src_y.left[1..]);
458 let mut left_u = [0; 8];
459 left_u.copy_from_slice(&src_u.left[1..9]);
460 let mut left_v = [0; 8];
461 left_v.copy_from_slice(&src_v.left[1..9]);
462 Self {
463 ipred_y: Intra4Pred::new(),
464 ipred_u: Intra4Pred::new(),
465 ipred_v: Intra4Pred::new(),
466 top_y, top_u, top_v, left_y, left_u, left_v,
467 has_l,
468 }
469 }
470 pub fn pred_block(&mut self, dst: &mut RefMBData, x: usize, y: usize, mode: PredType4x4) {
471 let do_chroma = ((x & 1) == 0) && ((y & 1) == 0);
472 if x == 0 {
473 self.ipred_y.tl = if y == 0 { self.top_y[0] } else { self.left_y[y * 4 - 1] };
474 if y != 3 {
475 self.ipred_y.left.copy_from_slice(&self.left_y[y * 4..][..8]);
476 } else {
477 self.ipred_y.left[..4].copy_from_slice(&self.left_y[12..]);
478 }
479 if y == 0 {
480 self.ipred_u.tl = self.top_u[0];
481 self.ipred_v.tl = self.top_v[0];
482 self.ipred_u.left.copy_from_slice(&self.left_u);
483 self.ipred_v.left.copy_from_slice(&self.left_v);
484 } else if y == 2 {
485 self.ipred_u.tl = self.left_u[3];
486 self.ipred_v.tl = self.left_v[3];
487 self.ipred_u.left[..4].copy_from_slice(&self.left_u[4..]);
488 self.ipred_v.left[..4].copy_from_slice(&self.left_v[4..]);
489 }
490 }
491 self.ipred_y.top.copy_from_slice(&self.top_y[x * 4 + 1..][..8]);
492 if do_chroma {
493 if x == 0 {
494 self.ipred_u.top.copy_from_slice(&self.top_u[1..9]);
495 self.ipred_v.top.copy_from_slice(&self.top_v[1..9]);
496 } else if x == 2 {
497 self.ipred_u.top.copy_from_slice(&self.top_u[5..]);
498 self.ipred_v.top.copy_from_slice(&self.top_v[5..]);
499 }
500 }
501
502 self.ipred_y.apply(mode, &mut dst.y[x * 4 + y * 4 * 16..], 16);
503 if do_chroma {
504 let has_ld = if (x == 0) && (y == 0) { self.has_l } else { false };
505 let off = x * 2 + y * 2 * 8;
506 let cmode = match mode {
507 PredType4x4::DiagDownLeft if !has_ld => PredType4x4::DiagDownLeftNoDown,
508 PredType4x4::VerLeft if !has_ld => PredType4x4::VerLeftNoDown,
509 PredType4x4::HorUp if !has_ld => PredType4x4::HorUpNoDown,
510 _ => mode,
511 };
512 self.ipred_u.apply(cmode, &mut dst.u[off..], 8);
513 self.ipred_v.apply(cmode, &mut dst.v[off..], 8);
514 }
515 }
516 pub fn update_from(&mut self, src: &RefMBData, x: usize, y: usize) {
517 let do_chroma = ((x & 1) == 0) && ((y & 1) == 0);
518 let y_off = x * 4 + y * 4 * 16;
519 let c_off = x * 2 + y * 2 * 8;
520
521 if x != 3 {
522 self.ipred_y.tl = self.ipred_y.top[3];
523 for (left, src) in self.ipred_y.left[..4].iter_mut().zip(src.y[y_off + 3..].chunks(16)) {
524 *left = src[0];
525 }
526 }
527 if do_chroma && x != 2 {
528 self.ipred_u.tl = self.ipred_u.top[3];
529 self.ipred_v.tl = self.ipred_v.top[3];
530 for (left, src) in self.ipred_u.left[..4].iter_mut().zip(src.u[c_off + 3..].chunks(8)) {
531 *left = src[0];
532 }
533 for (left, src) in self.ipred_v.left[..4].iter_mut().zip(src.v[c_off + 3..].chunks(8)) {
534 *left = src[0];
535 }
536 }
537 if x == 0 {
538 self.top_y[0] = self.left_y[x * 4 + 3];
539 if y == 0 {
540 self.top_u[0] = self.left_u[3];
541 self.top_v[0] = self.left_v[3];
542 }
543 }
544 self.top_y[x * 4 + 1..][..4].copy_from_slice(&src.y[y_off + 3 * 16..][..4]);
545 if x == 3 {
546 let (head, tail) = self.top_y.split_at_mut(17);
547 for el in tail.iter_mut() {
548 *el = head[16];
549 }
550 }
551 if do_chroma && y != 2 {
552 self.top_u[x * 2 + 1..][..4].copy_from_slice(&src.u[c_off + 3 * 8..][..4]);
553 self.top_v[x * 2 + 1..][..4].copy_from_slice(&src.v[c_off + 3 * 8..][..4]);
554 if x == 2 {
555 for i in 9..13 {
556 self.top_u[i] = self.top_u[8];
557 self.top_v[i] = self.top_v[8];
558 }
559 }
560 }
561 }
562}