split NihAV into subcrates
[nihav.git] / nihav-indeo / src / codecs / ividsp.rs
1 use super::ivi::{IVITransformType,TDir,TrFunc,TrFuncDC};
2
3 #[inline(always)]
4 fn hbutterfly(a: i32, b: i32) -> (i32, i32) {
5 ((a + b) >> 1, (a - b) >> 1)
6 }
7 #[inline(always)]
8 fn butterfly(a: i32, b: i32) -> (i32, i32) {
9 (a + b, a - b)
10 }
11 #[inline(always)]
12 fn ireflect(a: i32, b: i32) -> (i32, i32) {
13 (((b * 2 - a + 2) >> 2) - a, ((b + 2 * a + 2) >> 2) + b)
14 }
15
16 macro_rules! haar_transform {
17 ($c0:expr, $c1:expr, $c2:expr, $c3:expr) => {{
18 let (t0, t1) = hbutterfly($c0, $c1);
19 let (t2, t3) = hbutterfly(t0, $c2);
20 $c0 = t2;
21 $c1 = t3;
22 let (t4, t5) = hbutterfly(t1, $c3);
23 $c2 = t4;
24 $c3 = t5;
25 }};
26 ($c0:expr, $c1:expr, $c2:expr, $c3:expr, $c4:expr, $c5:expr, $c6:expr, $c7:expr) => {{
27 let (a0, a1) = hbutterfly($c0 << 1, $c1 << 1);
28
29 let (t0, t1) = hbutterfly(a0, $c2);
30 let (t2, t3) = hbutterfly(a1, $c3);
31 let (u0, u1) = hbutterfly(t0, $c4);
32 let (u2, u3) = hbutterfly(t1, $c5);
33 let (u4, u5) = hbutterfly(t2, $c6);
34 let (u6, u7) = hbutterfly(t3, $c7);
35
36 $c0 = u0;
37 $c1 = u1;
38 $c2 = u2;
39 $c3 = u3;
40 $c4 = u4;
41 $c5 = u5;
42 $c6 = u6;
43 $c7 = u7;
44 }};
45 }
46 macro_rules! slant_transform {
47 ($c0:expr, $c1:expr, $c2:expr, $c3:expr, $output:ident) => {{
48 let (t0, t1) = butterfly($c0, $c2);
49 let (t2, t3) = ireflect ($c3, $c1);
50 let (t4, t5) = butterfly(t0, t3);
51 let (t6, t7) = butterfly(t1, t2);
52 $c0 = $output(t4);
53 $c1 = $output(t6);
54 $c2 = $output(t7);
55 $c3 = $output(t5);
56 }};
57 ($c0:expr, $c1:expr, $c2:expr, $c3:expr, $c4:expr, $c5:expr, $c6:expr, $c7:expr, $output:ident) => {{
58 let t0 = $c3 + (($c1 * 4 - $c3 + 4) >> 3);
59 let t1 = $c1 + ((-$c1 - $c3 * 4 + 4) >> 3);
60
61 let (t2, t3) = butterfly($c0, t1);
62 let (t4, t5) = butterfly($c4, $c5);
63 let (t6, t7) = butterfly($c7, $c6);
64 let (t8, t9) = butterfly(t0, $c2);
65
66 let (u0, u1) = butterfly(t2, t4);
67 let (u2, u3) = ireflect (t7, t8);
68 let (u4, u5) = butterfly(t3, t5);
69 let (u6, u7) = ireflect (t6, t9);
70
71 let (t0, t1) = butterfly(u0, u3);
72 let (t2, t3) = butterfly(u1, u2);
73 let (t4, t5) = butterfly(u4, u7);
74 let (t6, t7) = butterfly(u5, u6);
75
76 $c0 = $output(t0);
77 $c1 = $output(t2);
78 $c2 = $output(t3);
79 $c3 = $output(t1);
80 $c4 = $output(t4);
81 $c5 = $output(t6);
82 $c6 = $output(t7);
83 $c7 = $output(t5);
84 }};
85 }
86
87 fn haar8x8_2d(blk: &mut[i32; 64]) {
88 for i in 0..4 {
89 let mut c0 = blk[i + 0*8] << 1;
90 let mut c1 = blk[i + 1*8] << 1;
91 let mut c2 = blk[i + 2*8] << 1;
92 let mut c3 = blk[i + 3*8] << 1;
93 haar_transform!(c0, c1, c2, c3,
94 blk[i + 4*8], blk[i + 5*8], blk[i + 6*8], blk[i + 7*8]);
95 blk[i + 0*8] = c0;
96 blk[i + 1*8] = c1;
97 blk[i + 2*8] = c2;
98 blk[i + 3*8] = c3;
99 }
100 for i in 4..8 {
101 haar_transform!(blk[i + 0*8], blk[i + 1*8], blk[i + 2*8], blk[i + 3*8],
102 blk[i + 4*8], blk[i + 5*8], blk[i + 6*8], blk[i + 7*8]);
103 }
104 for i in 0..8 {
105 let row = &mut blk[i*8..(i+1)*8];
106 haar_transform!(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
107 }
108 }
109 fn haar8x8_row(blk: &mut[i32; 64]) {
110 for i in 0..8 {
111 let row = &mut blk[i*8..(i+1)*8];
112 haar_transform!(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
113 }
114 }
115 fn haar8x8_col(blk: &mut[i32; 64]) {
116 for i in 0..8 {
117 haar_transform!(blk[i + 0*8], blk[i + 1*8], blk[i + 2*8], blk[i + 3*8],
118 blk[i + 4*8], blk[i + 5*8], blk[i + 6*8], blk[i + 7*8]);
119 }
120 }
121 fn haar8x8_dc(blk: &mut[i32; 64], in0: i32) {
122 let dc = in0 >> 3;
123 for i in 0..64 { blk[i] = dc; }
124 }
125
126 fn haar4x4_2d(blk: &mut[i32; 64]) {
127 for i in 0..2 {
128 let mut c0 = blk[i + 0*4] << 1;
129 let mut c1 = blk[i + 1*4] << 1;
130 haar_transform!(c0, c1, blk[i + 2*4], blk[i + 3*4]);
131 blk[i + 0*4] = c0;
132 blk[i + 1*4] = c1;
133 }
134 for i in 2..4 {
135 haar_transform!(blk[i + 0*4], blk[i + 1*4], blk[i + 2*4], blk[i + 3*4]);
136 }
137 for i in 0..4 {
138 let row = &mut blk[i*4..(i+1)*4];
139 haar_transform!(row[0], row[1], row[2], row[3]);
140 }
141 }
142 fn haar4x4_row(blk: &mut[i32; 64]) {
143 for i in 0..4 {
144 let row = &mut blk[i*4..(i+1)*4];
145 haar_transform!(row[0], row[1], row[2], row[3]);
146 }
147 }
148 fn haar4x4_col(blk: &mut[i32; 64]) {
149 for i in 0..4 {
150 haar_transform!(blk[i + 0*4], blk[i + 1*4], blk[i + 2*4], blk[i + 3*4]);
151 }
152 }
153 fn haar4x4_dc(blk: &mut[i32; 64], in0: i32) {
154 let dc = in0 >> 3;
155 for i in 0..16 { blk[i] = dc; }
156 }
157
158 fn slant8x8_2d(blk: &mut[i32; 64]) {
159 let pass1 = |x: i32| x;
160 let pass2 = |x: i32| (x + 1) >> 1;
161
162 for i in 0..8 {
163 let mut s0 = 0;
164 for j in 0..8 { s0 |= blk[i + j*8]; }
165 if s0 == 0 { continue; }
166
167 slant_transform!(blk[i + 0*8], blk[i + 1*8], blk[i + 2*8], blk[i + 3*8],
168 blk[i + 4*8], blk[i + 5*8], blk[i + 6*8], blk[i + 7*8], pass1);
169 }
170 for i in 0..8 {
171 let row = &mut blk[i*8..(i+1)*8];
172 slant_transform!(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], pass2);
173 }
174 }
175 fn slant8x8_2d_dc(blk: &mut[i32; 64], in0: i32) {
176 let dc = (in0 + 1) >> 1;
177 for i in 0..64 { blk[i] = dc; }
178 }
179 fn slant8x8_row(blk: &mut[i32; 64]) {
180 let pass = |x: i32| (x + 1) >> 1;
181
182 for i in 0..8 {
183 let row = &mut blk[i*8..(i+1)*8];
184 slant_transform!(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], pass);
185 }
186 }
187 fn slant8x8_row_dc(blk: &mut[i32; 64], in0: i32) {
188 let dc = (in0 + 1) >> 1;
189
190 for i in 0..8 { blk[i] = dc; }
191 for i in 8..64 { blk[i] = 0; }
192 }
193 fn slant8x8_col(blk: &mut[i32; 64]) {
194 let pass = |x: i32| (x + 1) >> 1;
195
196 for i in 0..8 {
197 slant_transform!(blk[i + 0*8], blk[i + 1*8], blk[i + 2*8], blk[i + 3*8],
198 blk[i + 4*8], blk[i + 5*8], blk[i + 6*8], blk[i + 7*8], pass);
199 }
200 }
201 fn slant8x8_col_dc(blk: &mut[i32; 64], in0: i32) {
202 let dc = (in0 + 1) >> 1;
203
204 for i in 0..8 {
205 blk[i * 8] = dc;
206 for j in 1..8 { blk[i * 8 + j] = 0; }
207 }
208 }
209
210 fn slant4x4_2d(blk: &mut[i32; 64]) {
211 let pass1 = |x: i32| x;
212 let pass2 = |x: i32| (x + 1) >> 1;
213
214 for i in 0..4 {
215 slant_transform!(blk[i + 0*4], blk[i + 1*4], blk[i + 2*4], blk[i + 3*4], pass1);
216 }
217 for i in 0..4 {
218 let row = &mut blk[i*4..(i+1)*4];
219 slant_transform!(row[0], row[1], row[2], row[3], pass2);
220 }
221 }
222 fn slant4x4_2d_dc(blk: &mut[i32; 64], in0: i32) {
223 let dc = (in0 + 1) >> 1;
224 for i in 0..16 { blk[i] = dc; }
225 }
226 fn slant4x4_row(blk: &mut[i32; 64]) {
227 let pass = |x: i32| (x + 1) >> 1;
228
229 for i in 0..4 {
230 let row = &mut blk[i*4..(i+1)*4];
231 slant_transform!(row[0], row[1], row[2], row[3], pass);
232 }
233 }
234 fn slant4x4_row_dc(blk: &mut[i32; 64], in0: i32) {
235 let dc = (in0 + 1) >> 1;
236
237 for i in 0..4 { blk[i] = dc; }
238 for i in 4..16 { blk[i] = 0; }
239 }
240 fn slant4x4_col(blk: &mut[i32; 64]) {
241 let pass = |x: i32| (x + 1) >> 1;
242
243 for i in 0..4 {
244 slant_transform!(blk[i + 0*4], blk[i + 1*4], blk[i + 2*4], blk[i + 3*4], pass);
245 }
246 }
247 fn slant4x4_col_dc(blk: &mut[i32; 64], in0: i32) {
248 let dc = (in0 + 1) >> 1;
249
250 for i in 0..4 {
251 blk[i * 4] = dc;
252 for j in 1..4 { blk[i * 4 + j] = 0; }
253 }
254 }
255
256 #[allow(unused_variables)]
257 fn none8x8(blk: &mut[i32; 64]) {
258 }
259 fn none8x8_dc(blk: &mut[i32; 64], dc: i32) {
260 for i in 1..8 { blk[i] = dc; }
261 for i in 8..64 { blk[i] = 0; }
262 }
263 #[allow(unused_variables)]
264 fn none4x4(blk: &mut[i32; 64]) {
265 }
266 fn none4x4_dc(blk: &mut[i32; 64], dc: i32) {
267 for i in 1..4 { blk[i] = dc; }
268 for i in 4..16 { blk[i] = 0; }
269 }
270
271 pub fn ivi_get_transform8x8_funcs(ttype: IVITransformType) -> (TrFunc, TrFuncDC) {
272 match ttype {
273 IVITransformType::Haar(_, ref dir) => {
274 match *dir {
275 TDir::TwoD => { (haar8x8_2d, haar8x8_dc) },
276 TDir::Row => { (haar8x8_row, haar8x8_dc) },
277 TDir::Col => { (haar8x8_col, haar8x8_dc) },
278 } },
279 IVITransformType::Slant(_, ref dir) => {
280 match *dir {
281 TDir::TwoD => { (slant8x8_2d, slant8x8_2d_dc) },
282 TDir::Row => { (slant8x8_row, slant8x8_row_dc) },
283 TDir::Col => { (slant8x8_col, slant8x8_col_dc) },
284 } },
285 IVITransformType::DCT(_, _) => { unimplemented!() },
286 IVITransformType::None(_) => { (none8x8, none8x8_dc) }
287 }
288 }
289 pub fn ivi_get_transform4x4_funcs(ttype: IVITransformType) -> (TrFunc, TrFuncDC) {
290 match ttype {
291 IVITransformType::Haar(_, ref dir) => {
292 match *dir {
293 TDir::TwoD => { (haar4x4_2d, haar4x4_dc) },
294 TDir::Row => { (haar4x4_row, haar4x4_dc) },
295 TDir::Col => { (haar4x4_col, haar4x4_dc) },
296 } },
297 IVITransformType::Slant(_, ref dir) => {
298 match *dir {
299 TDir::TwoD => { (slant4x4_2d, slant4x4_2d_dc) },
300 TDir::Row => { (slant4x4_row, slant4x4_row_dc) },
301 TDir::Col => { (slant4x4_col, slant4x4_col_dc) },
302 } },
303 IVITransformType::DCT(_, _) => { unimplemented!() },
304 IVITransformType::None(_) => { (none4x4, none4x4_dc) }
305 }
306 }
307
308 pub fn ivi_mc_put(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize, mode: u8, w: usize, h: usize) {
309 let mut sidx = 0;
310 let mut didx = 0;
311 if src.len() < w + h * sstride { return; }
312 match mode {
313 0 => {
314 for _ in 0..h {
315 let dest = &mut dst[didx..didx+w];
316 dest.copy_from_slice(&src[sidx..sidx+w]);
317 sidx += sstride;
318 didx += dstride;
319 }
320 },
321 1 => {
322 /*for _ in 0..h {
323 for x in 0..w {
324 let val = (src[sidx + x] + src[sidx + x + 1]) >> 1;
325 dst[didx + x] = val;
326 }
327 sidx += sstride;
328 didx += dstride;
329 }*/
330 unsafe {
331 let mut sptr = src.as_ptr();
332 let mut dptr = dst.as_mut_ptr();
333 for _ in 0..h {
334 let mut last = *sptr;
335 for x in 0..w {
336 let nv = *sptr.offset((x + 1) as isize);
337 *dptr.offset(x as isize) = nv.wrapping_add(last) >> 1;
338 last = nv;
339 }
340 sptr = sptr.offset(sstride as isize);
341 dptr = dptr.offset(dstride as isize);
342 }
343 }
344 },
345 2 => {
346 /*for _ in 0..h {
347 for x in 0..w {
348 let val = (src[sidx + x] + src[sidx + x + sstride]) >> 1;
349 dst[didx + x] = val;
350 }
351 sidx += sstride;
352 didx += dstride;
353 }*/
354 unsafe {
355 let mut sptr0 = src.as_ptr();
356 let mut sptr1 = sptr0.offset(sstride as isize);
357 let mut dptr = dst.as_mut_ptr();
358 for _ in 0..h {
359 for x in 0..w {
360 let a = *sptr0.offset(x as isize);
361 let b = *sptr1.offset(x as isize);
362 *dptr.offset(x as isize) = a.wrapping_add(b) >> 1;
363 }
364 sptr0 = sptr0.offset(sstride as isize);
365 sptr1 = sptr1.offset(sstride as isize);
366 dptr = dptr.offset(sstride as isize);
367 }
368 }
369 },
370 3 => {
371 /*for _ in 0..h {
372 for x in 0..w {
373 let val = (src[sidx + x + 0] + src[sidx + x + sstride + 0] +
374 src[sidx + x + 1] + src[sidx + x + sstride + 1]) >> 2;
375 dst[didx + x] = val;
376 }
377 sidx += sstride;
378 didx += dstride;
379 }*/
380 unsafe {
381 let mut sptr0 = src.as_ptr();
382 let mut sptr1 = sptr0.offset(sstride as isize);
383 let mut dptr = dst.as_mut_ptr();
384 let mut la = *sptr0;
385 let mut lb = *sptr1;
386 for _ in 0..h {
387 for x in 0..w {
388 let a = *sptr0.offset((x + 1) as isize);
389 let b = *sptr1.offset((x + 1) as isize);
390 let aas = a.wrapping_add(la);
391 let bbs = b.wrapping_add(lb);
392 *dptr.offset(x as isize) = aas.wrapping_add(bbs) >> 2;
393 la = a;
394 lb = b;
395 }
396 sptr0 = sptr0.offset(sstride as isize);
397 sptr1 = sptr1.offset(sstride as isize);
398 dptr = dptr.offset(dstride as isize);
399 }
400 }
401 },
402 _ => {},
403 }
404 }
405 fn ivi_mc_add(dst: &mut [i16], dstride: usize, src: &[i16], sstride: usize, mode: u8, w: usize, h: usize) {
406 let mut sidx = 0;
407 let mut didx = 0;
408 match mode {
409 0 => {
410 for _ in 0..h {
411 for x in 0..w {
412 dst[didx + x] += src[sidx + x];
413 }
414 sidx += sstride;
415 didx += dstride;
416 }
417 },
418 1 => {
419 for _ in 0..h {
420 for x in 0..w {
421 let val = (src[sidx + x] + src[sidx + x + 1]) >> 1;
422 dst[didx + x] += val;
423 }
424 sidx += sstride;
425 didx += dstride;
426 }
427 },
428 2 => {
429 for _ in 0..h {
430 for x in 0..w {
431 let val = (src[sidx + x] + src[sidx + x + sstride]) >> 1;
432 dst[didx + x] += val;
433 }
434 sidx += sstride;
435 didx += dstride;
436 }
437 },
438 3 => {
439 for _ in 0..h {
440 for x in 0..w {
441 let val = (src[sidx + x + 0] + src[sidx + x + sstride + 0] +
442 src[sidx + x + 1] + src[sidx + x + sstride + 1]) >> 2;
443 dst[didx + x] += val;
444 }
445 sidx += sstride;
446 didx += dstride;
447 }
448 },
449 _ => {},
450 }
451 }
452 pub fn ivi_mc_avg(dst: &mut [i16], dstride: usize,
453 src1: &[i16], sstride1: usize, mode1: u8,
454 src2: &[i16], sstride2: usize, mode2: u8,
455 w: usize, h: usize) {
456 let mut tidx = 0;
457 let tstride = 8;
458 let mut didx = 0;
459 let mut tmp: [i16; 64] = [0; 64];
460 ivi_mc_add(&mut tmp, tstride, src1, sstride1, mode1, w, h);
461 ivi_mc_add(&mut tmp, tstride, src2, sstride2, mode2, w, h);
462 for _ in 0..h {
463 for x in 0..w { dst[didx + x] = tmp[tidx + x] >> 1; }
464 tidx += tstride;
465 didx += dstride;
466 }
467 }