]> git.sesse.net Git - ffmpeg/blob - libavcodec/simple_idct.c
9edb7262a809b916c2cd4ff5d0bee8b7a4acff8a
[ffmpeg] / libavcodec / simple_idct.c
1 /*
2  * Simple IDCT
3  *
4  * Copyright (c) 2001 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 /*
21   based upon some outcommented c code from mpeg2dec (idct_mmx.c
22   written by Aaron Holtzman <aholtzma@ess.engr.uvic.ca>) 
23  */
24 #include "avcodec.h"
25 #include "dsputil.h"
26 #include "simple_idct.h"
27
28 #if 0
29 #define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */
30 #define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */
31 #define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */
32 #define W4 2048 /* 2048*sqrt (2)*cos (4*pi/16) */
33 #define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */
34 #define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */
35 #define W7 565  /* 2048*sqrt (2)*cos (7*pi/16) */
36 #define ROW_SHIFT 8
37 #define COL_SHIFT 17
38 #else
39 #define W1  22725  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
40 #define W2  21407  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
41 #define W3  19266  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
42 #define W4  16383  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
43 #define W5  12873  //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
44 #define W6  8867   //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
45 #define W7  4520   //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5
46 #define ROW_SHIFT 11
47 #define COL_SHIFT 20 // 6
48 #endif
49
50 #ifdef ARCH_ALPHA
51 #define FAST_64BIT
52 #endif
53
54 #if defined(ARCH_POWERPC_405)
55
56 /* signed 16x16 -> 32 multiply add accumulate */
57 #define MAC16(rt, ra, rb) \
58     asm ("maclhw %0, %2, %3" : "=r" (rt) : "0" (rt), "r" (ra), "r" (rb));
59
60 /* signed 16x16 -> 32 multiply */
61 #define MUL16(rt, ra, rb) \
62     asm ("mullhw %0, %1, %2" : "=r" (rt) : "r" (ra), "r" (rb));
63
64 #else
65
66 /* signed 16x16 -> 32 multiply add accumulate */
67 #define MAC16(rt, ra, rb) rt += (ra) * (rb)
68
69 /* signed 16x16 -> 32 multiply */
70 #define MUL16(rt, ra, rb) rt = (ra) * (rb)
71
72 #endif
73
74 #ifdef ARCH_ALPHA
75 /* 0: all entries 0, 1: only first entry nonzero, 2: otherwise  */
76 static inline int idctRowCondDC(int16_t *row)
77 {
78         int_fast32_t a0, a1, a2, a3, b0, b1, b2, b3;
79         uint64_t *lrow = (uint64_t *) row;
80
81         if (lrow[1] == 0) {
82                 if (lrow[0] == 0)
83                         return 0;
84                 if ((lrow[0] & ~0xffffULL) == 0) {
85                         uint64_t v;
86
87                         a0 = W4 * row[0];
88                         a0 += 1 << (ROW_SHIFT - 1);
89                         a0 >>= ROW_SHIFT;
90                         v = (uint16_t) a0;
91                         v += v << 16;
92                         v += v << 32;
93                         lrow[0] = v;
94                         lrow[1] = v;
95
96                         return 1;
97                 }
98         }
99
100         a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1));
101         a1 = a0;
102         a2 = a0;
103         a3 = a0;
104
105         if (row[2]) {
106                 a0 += W2 * row[2];
107                 a1 += W6 * row[2];
108                 a2 -= W6 * row[2];
109                 a3 -= W2 * row[2];
110         }
111
112         if (row[4]) {
113                 a0 += W4 * row[4];
114                 a1 -= W4 * row[4];
115                 a2 -= W4 * row[4];
116                 a3 += W4 * row[4];
117         }
118
119         if (row[6]) {
120                 a0 += W6 * row[6];
121                 a1 -= W2 * row[6];
122                 a2 += W2 * row[6];
123                 a3 -= W6 * row[6];
124         }
125
126         if (row[1]) {
127                 b0 = W1 * row[1];
128                 b1 = W3 * row[1];
129                 b2 = W5 * row[1];
130                 b3 = W7 * row[1];
131         } else {
132                 b0 = 0;
133                 b1 = 0;
134                 b2 = 0;
135                 b3 = 0;
136         }
137
138         if (row[3]) {
139                 b0 += W3 * row[3];
140                 b1 -= W7 * row[3];
141                 b2 -= W1 * row[3];
142                 b3 -= W5 * row[3];
143         }
144
145         if (row[5]) {
146                 b0 += W5 * row[5];
147                 b1 -= W1 * row[5];
148                 b2 += W7 * row[5];
149                 b3 += W3 * row[5];
150         }
151
152         if (row[7]) {
153                 b0 += W7 * row[7];
154                 b1 -= W5 * row[7];
155                 b2 += W3 * row[7];
156                 b3 -= W1 * row[7];
157         }
158
159         row[0] = (a0 + b0) >> ROW_SHIFT;
160         row[1] = (a1 + b1) >> ROW_SHIFT;
161         row[2] = (a2 + b2) >> ROW_SHIFT;
162         row[3] = (a3 + b3) >> ROW_SHIFT;
163         row[4] = (a3 - b3) >> ROW_SHIFT;
164         row[5] = (a2 - b2) >> ROW_SHIFT;
165         row[6] = (a1 - b1) >> ROW_SHIFT;
166         row[7] = (a0 - b0) >> ROW_SHIFT;
167
168         return 2;
169 }
170
171 inline static void idctSparseCol(int16_t *col)
172 {
173         int a0, a1, a2, a3, b0, b1, b2, b3;
174
175         col[0] += (1 << (COL_SHIFT - 1)) / W4;
176
177         a0 = W4 * col[8 * 0];
178         a1 = W4 * col[8 * 0];
179         a2 = W4 * col[8 * 0];
180         a3 = W4 * col[8 * 0];
181
182         if (col[8 * 2]) {
183                 a0 += W2 * col[8 * 2];
184                 a1 += W6 * col[8 * 2];
185                 a2 -= W6 * col[8 * 2];
186                 a3 -= W2 * col[8 * 2];
187         }
188
189         if (col[8 * 4]) {
190                 a0 += W4 * col[8 * 4];
191                 a1 -= W4 * col[8 * 4];
192                 a2 -= W4 * col[8 * 4];
193                 a3 += W4 * col[8 * 4];
194         }
195
196         if (col[8 * 6]) {
197                 a0 += W6 * col[8 * 6];
198                 a1 -= W2 * col[8 * 6];
199                 a2 += W2 * col[8 * 6];
200                 a3 -= W6 * col[8 * 6];
201         }
202
203         if (col[8 * 1]) {
204                 b0 = W1 * col[8 * 1];
205                 b1 = W3 * col[8 * 1];
206                 b2 = W5 * col[8 * 1];
207                 b3 = W7 * col[8 * 1];
208         } else {
209                 b0 = b1 = b2 = b3 = 0;
210         }
211
212         if (col[8 * 3]) {
213                 b0 += W3 * col[8 * 3];
214                 b1 -= W7 * col[8 * 3];
215                 b2 -= W1 * col[8 * 3];
216                 b3 -= W5 * col[8 * 3];
217         }
218
219         if (col[8 * 5]) {
220                 b0 += W5 * col[8 * 5];
221                 b1 -= W1 * col[8 * 5];
222                 b2 += W7 * col[8 * 5];
223                 b3 += W3 * col[8 * 5];
224         }
225
226         if (col[8 * 7]) {
227                 b0 += W7 * col[8 * 7];
228                 b1 -= W5 * col[8 * 7];
229                 b2 += W3 * col[8 * 7];
230                 b3 -= W1 * col[8 * 7];
231         }
232
233         col[8 * 0] = (a0 + b0) >> COL_SHIFT;
234         col[8 * 7] = (a0 - b0) >> COL_SHIFT;
235         col[8 * 1] = (a1 + b1) >> COL_SHIFT;
236         col[8 * 6] = (a1 - b1) >> COL_SHIFT;
237         col[8 * 2] = (a2 + b2) >> COL_SHIFT;
238         col[8 * 5] = (a2 - b2) >> COL_SHIFT;
239         col[8 * 3] = (a3 + b3) >> COL_SHIFT;
240         col[8 * 4] = (a3 - b3) >> COL_SHIFT;
241 }
242
243 #else  /* not ARCH_ALPHA */
244
245 static inline void idctRowCondDC (int16_t * row)
246 {
247         int a0, a1, a2, a3, b0, b1, b2, b3;
248 #ifdef FAST_64BIT
249         uint64_t temp;
250 #else
251         uint32_t temp;
252 #endif
253
254 #ifdef FAST_64BIT
255 #ifdef WORDS_BIGENDIAN
256 #define ROW0_MASK 0xffff000000000000LL
257 #else
258 #define ROW0_MASK 0xffffLL
259 #endif
260         if ( ((((uint64_t *)row)[0] & ~ROW0_MASK) | 
261               ((uint64_t *)row)[1]) == 0) {
262             temp = (row[0] << 3) & 0xffff;
263             temp += temp << 16;
264             temp += temp << 32;
265             ((uint64_t *)row)[0] = temp;
266             ((uint64_t *)row)[1] = temp;
267             return;
268         }
269 #else
270         if (!(((uint32_t*)row)[1] |
271               ((uint32_t*)row)[2] |
272               ((uint32_t*)row)[3] | 
273               row[1])) {
274             temp = (row[0] << 3) & 0xffff;
275             temp += temp << 16;
276             ((uint32_t*)row)[0]=((uint32_t*)row)[1] =
277                 ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp;
278                 return;
279         }
280 #endif
281
282         a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1));
283         a1 = a0;
284         a2 = a0;
285         a3 = a0;
286
287         /* no need to optimize : gcc does it */
288         a0 += W2 * row[2];
289         a1 += W6 * row[2];
290         a2 -= W6 * row[2];
291         a3 -= W2 * row[2];
292
293         MUL16(b0, W1, row[1]);
294         MAC16(b0, W3, row[3]);
295         MUL16(b1, W3, row[1]);
296         MAC16(b1, -W7, row[3]);
297         MUL16(b2, W5, row[1]);
298         MAC16(b2, -W1, row[3]);
299         MUL16(b3, W7, row[1]);
300         MAC16(b3, -W5, row[3]);
301
302 #ifdef FAST_64BIT
303         temp = ((uint64_t*)row)[1];
304 #else
305         temp = ((uint32_t*)row)[2] | ((uint32_t*)row)[3];
306 #endif
307         if (temp != 0) {
308             a0 += W4*row[4] + W6*row[6];
309             a1 += - W4*row[4] - W2*row[6];
310             a2 += - W4*row[4] + W2*row[6];
311             a3 += W4*row[4] - W6*row[6];
312
313             MAC16(b0, W5, row[5]);
314             MAC16(b0, W7, row[7]);
315             
316             MAC16(b1, -W1, row[5]);
317             MAC16(b1, -W5, row[7]);
318             
319             MAC16(b2, W7, row[5]);
320             MAC16(b2, W3, row[7]);
321             
322             MAC16(b3, W3, row[5]);
323             MAC16(b3, -W1, row[7]);
324         }
325
326         row[0] = (a0 + b0) >> ROW_SHIFT;
327         row[7] = (a0 - b0) >> ROW_SHIFT;
328         row[1] = (a1 + b1) >> ROW_SHIFT;
329         row[6] = (a1 - b1) >> ROW_SHIFT;
330         row[2] = (a2 + b2) >> ROW_SHIFT;
331         row[5] = (a2 - b2) >> ROW_SHIFT;
332         row[3] = (a3 + b3) >> ROW_SHIFT;
333         row[4] = (a3 - b3) >> ROW_SHIFT;
334 }
335 #endif /* not ARCH_ALPHA */
336
337 static inline void idctSparseColPut (UINT8 *dest, int line_size, 
338                                      int16_t * col)
339 {
340         int a0, a1, a2, a3, b0, b1, b2, b3;
341         UINT8 *cm = cropTbl + MAX_NEG_CROP;
342
343         /* XXX: I did that only to give same values as previous code */
344         a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
345         a1 = a0;
346         a2 = a0;
347         a3 = a0;
348
349         a0 +=  + W2*col[8*2];
350         a1 +=  + W6*col[8*2];
351         a2 +=  - W6*col[8*2];
352         a3 +=  - W2*col[8*2];
353
354         MUL16(b0, W1, col[8*1]);
355         MUL16(b1, W3, col[8*1]);
356         MUL16(b2, W5, col[8*1]);
357         MUL16(b3, W7, col[8*1]);
358
359         MAC16(b0, + W3, col[8*3]);
360         MAC16(b1, - W7, col[8*3]);
361         MAC16(b2, - W1, col[8*3]);
362         MAC16(b3, - W5, col[8*3]);
363
364         if(col[8*4]){
365             a0 += + W4*col[8*4];
366             a1 += - W4*col[8*4];
367             a2 += - W4*col[8*4];
368             a3 += + W4*col[8*4];
369         }
370
371         if (col[8*5]) {
372             MAC16(b0, + W5, col[8*5]);
373             MAC16(b1, - W1, col[8*5]);
374             MAC16(b2, + W7, col[8*5]);
375             MAC16(b3, + W3, col[8*5]);
376         }
377
378         if(col[8*6]){
379             a0 += + W6*col[8*6];
380             a1 += - W2*col[8*6];
381             a2 += + W2*col[8*6];
382             a3 += - W6*col[8*6];
383         }
384
385         if (col[8*7]) {
386             MAC16(b0, + W7, col[8*7]);
387             MAC16(b1, - W5, col[8*7]);
388             MAC16(b2, + W3, col[8*7]);
389             MAC16(b3, - W1, col[8*7]);
390         }
391
392         dest[0] = cm[(a0 + b0) >> COL_SHIFT];
393         dest += line_size;
394         dest[0] = cm[(a1 + b1) >> COL_SHIFT];
395         dest += line_size;
396         dest[0] = cm[(a2 + b2) >> COL_SHIFT];
397         dest += line_size;
398         dest[0] = cm[(a3 + b3) >> COL_SHIFT];
399         dest += line_size;
400         dest[0] = cm[(a3 - b3) >> COL_SHIFT];
401         dest += line_size;
402         dest[0] = cm[(a2 - b2) >> COL_SHIFT];
403         dest += line_size;
404         dest[0] = cm[(a1 - b1) >> COL_SHIFT];
405         dest += line_size;
406         dest[0] = cm[(a0 - b0) >> COL_SHIFT];
407 }
408
409 static inline void idctSparseColAdd (UINT8 *dest, int line_size, 
410                                      int16_t * col)
411 {
412         int a0, a1, a2, a3, b0, b1, b2, b3;
413         UINT8 *cm = cropTbl + MAX_NEG_CROP;
414
415         /* XXX: I did that only to give same values as previous code */
416         a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4));
417         a1 = a0;
418         a2 = a0;
419         a3 = a0;
420
421         a0 +=  + W2*col[8*2];
422         a1 +=  + W6*col[8*2];
423         a2 +=  - W6*col[8*2];
424         a3 +=  - W2*col[8*2];
425
426         MUL16(b0, W1, col[8*1]);
427         MUL16(b1, W3, col[8*1]);
428         MUL16(b2, W5, col[8*1]);
429         MUL16(b3, W7, col[8*1]);
430
431         MAC16(b0, + W3, col[8*3]);
432         MAC16(b1, - W7, col[8*3]);
433         MAC16(b2, - W1, col[8*3]);
434         MAC16(b3, - W5, col[8*3]);
435
436         if(col[8*4]){
437             a0 += + W4*col[8*4];
438             a1 += - W4*col[8*4];
439             a2 += - W4*col[8*4];
440             a3 += + W4*col[8*4];
441         }
442
443         if (col[8*5]) {
444             MAC16(b0, + W5, col[8*5]);
445             MAC16(b1, - W1, col[8*5]);
446             MAC16(b2, + W7, col[8*5]);
447             MAC16(b3, + W3, col[8*5]);
448         }
449
450         if(col[8*6]){
451             a0 += + W6*col[8*6];
452             a1 += - W2*col[8*6];
453             a2 += + W2*col[8*6];
454             a3 += - W6*col[8*6];
455         }
456
457         if (col[8*7]) {
458             MAC16(b0, + W7, col[8*7]);
459             MAC16(b1, - W5, col[8*7]);
460             MAC16(b2, + W3, col[8*7]);
461             MAC16(b3, - W1, col[8*7]);
462         }
463
464         dest[0] = cm[dest[0] + ((a0 + b0) >> COL_SHIFT)];
465         dest += line_size;
466         dest[0] = cm[dest[0] + ((a1 + b1) >> COL_SHIFT)];
467         dest += line_size;
468         dest[0] = cm[dest[0] + ((a2 + b2) >> COL_SHIFT)];
469         dest += line_size;
470         dest[0] = cm[dest[0] + ((a3 + b3) >> COL_SHIFT)];
471         dest += line_size;
472         dest[0] = cm[dest[0] + ((a3 - b3) >> COL_SHIFT)];
473         dest += line_size;
474         dest[0] = cm[dest[0] + ((a2 - b2) >> COL_SHIFT)];
475         dest += line_size;
476         dest[0] = cm[dest[0] + ((a1 - b1) >> COL_SHIFT)];
477         dest += line_size;
478         dest[0] = cm[dest[0] + ((a0 - b0) >> COL_SHIFT)];
479 }
480
481 #ifdef ARCH_ALPHA
482 /* If all rows but the first one are zero after row transformation,
483    all rows will be identical after column transformation.  */
484 static inline void idctCol2(int16_t *col)
485 {
486         int i;
487         uint64_t l, r;
488         uint64_t *lcol = (uint64_t *) col;
489
490         for (i = 0; i < 8; ++i) {
491                 int a0 = col[0] + (1 << (COL_SHIFT - 1)) / W4;
492
493                 a0 *= W4;
494                 col[0] = a0 >> COL_SHIFT;
495                 ++col;
496         }
497
498         l = lcol[0];
499         r = lcol[1];
500         lcol[ 2] = l; lcol[ 3] = r;
501         lcol[ 4] = l; lcol[ 5] = r;
502         lcol[ 6] = l; lcol[ 7] = r;
503         lcol[ 8] = l; lcol[ 9] = r;
504         lcol[10] = l; lcol[11] = r;
505         lcol[12] = l; lcol[13] = r;
506         lcol[14] = l; lcol[15] = r;
507 }
508
509 void simple_idct (short *block)
510 {
511
512         int i;
513         int rowsZero = 1;       /* all rows except row 0 zero */
514         int rowsConstant = 1;   /* all rows consist of a constant value */
515
516         for (i = 0; i < 8; i++) {
517                 int sparseness = idctRowCondDC(block + 8 * i);
518
519                 if (i > 0 && sparseness > 0)
520                         rowsZero = 0;
521                 if (sparseness == 2)
522                         rowsConstant = 0;
523         }
524
525         if (rowsZero) {
526                 idctCol2(block);
527         } else if (rowsConstant) {
528                 uint64_t *lblock = (uint64_t *) block;
529
530                 idctSparseCol(block);
531                 for (i = 0; i < 8; i++) {
532                         uint64_t v = (uint16_t) block[i * 8];
533
534                         v += v << 16;
535                         v += v << 32;
536                         lblock[0] = v;
537                         lblock[1] = v;
538                         lblock += 2;
539                 }
540         } else {
541                 for (i = 0; i < 8; i++)
542                         idctSparseCol(block + i);
543         }
544 }
545
546 /* XXX: suppress this mess */
547 void simple_idct_put(UINT8 *dest, int line_size, DCTELEM *block)
548 {
549     simple_idct(block);
550     put_pixels_clamped(block, dest, line_size);
551 }
552
553 void simple_idct_add(UINT8 *dest, int line_size, DCTELEM *block)
554 {
555     simple_idct(block);
556     add_pixels_clamped(block, dest, line_size);
557 }
558
559 #else
560
561 void simple_idct_put(UINT8 *dest, int line_size, INT16 *block)
562 {
563     int i;
564     for(i=0; i<8; i++)
565         idctRowCondDC(block + i*8);
566     
567     for(i=0; i<8; i++)
568         idctSparseColPut(dest + i, line_size, block + i);
569 }
570
571 void simple_idct_add(UINT8 *dest, int line_size, INT16 *block)
572 {
573     int i;
574     for(i=0; i<8; i++)
575         idctRowCondDC(block + i*8);
576     
577     for(i=0; i<8; i++)
578         idctSparseColAdd(dest + i, line_size, block + i);
579 }
580
581 #endif
582
583 #undef COL_SHIFT