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