]>
Commit | Line | Data |
---|---|---|
4965a5e5 KS |
1 | use super::super::types::{PredType8x8, PredType4x4}; |
2 | use super::RefMBData; | |
3 | ||
4 | #[derive(Default)] | |
5 | pub struct IntraPred16x16 { | |
6 | pub top: [u8; 17], | |
7 | pub left: [u8; 17], | |
8 | } | |
9 | ||
10 | impl 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)] | |
136 | pub struct Intra4Pred { | |
137 | pub top: [u8; 8], | |
138 | pub left: [u8; 8], | |
139 | pub tl: u8, | |
140 | } | |
141 | ||
142 | impl 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 | ||
432 | pub 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 | ||
445 | impl 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 | } |