00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "libavcodec/dsputil.h"
00030 #include "dsputil_alpha.h"
00031 #include "asm.h"
00032
00033
00034
00035
00036 #define W1 22725
00037 #define W2 21407
00038 #define W3 19266
00039 #define W4 16383
00040 #define W5 12873
00041 #define W6 8867
00042 #define W7 4520
00043 #define ROW_SHIFT 11
00044 #define COL_SHIFT 20
00045
00046
00047 static inline int idct_row(DCTELEM *row)
00048 {
00049 int a0, a1, a2, a3, b0, b1, b2, b3, t;
00050 uint64_t l, r, t2;
00051 l = ldq(row);
00052 r = ldq(row + 4);
00053
00054 if (l == 0 && r == 0)
00055 return 0;
00056
00057 a0 = W4 * sextw(l) + (1 << (ROW_SHIFT - 1));
00058
00059 if (((l & ~0xffffUL) | r) == 0) {
00060 a0 >>= ROW_SHIFT;
00061 t2 = (uint16_t) a0;
00062 t2 |= t2 << 16;
00063 t2 |= t2 << 32;
00064
00065 stq(t2, row);
00066 stq(t2, row + 4);
00067 return 1;
00068 }
00069
00070 a1 = a0;
00071 a2 = a0;
00072 a3 = a0;
00073
00074 t = extwl(l, 4);
00075 if (t != 0) {
00076 t = sextw(t);
00077 a0 += W2 * t;
00078 a1 += W6 * t;
00079 a2 -= W6 * t;
00080 a3 -= W2 * t;
00081 }
00082
00083 t = extwl(r, 0);
00084 if (t != 0) {
00085 t = sextw(t);
00086 a0 += W4 * t;
00087 a1 -= W4 * t;
00088 a2 -= W4 * t;
00089 a3 += W4 * t;
00090 }
00091
00092 t = extwl(r, 4);
00093 if (t != 0) {
00094 t = sextw(t);
00095 a0 += W6 * t;
00096 a1 -= W2 * t;
00097 a2 += W2 * t;
00098 a3 -= W6 * t;
00099 }
00100
00101 t = extwl(l, 2);
00102 if (t != 0) {
00103 t = sextw(t);
00104 b0 = W1 * t;
00105 b1 = W3 * t;
00106 b2 = W5 * t;
00107 b3 = W7 * t;
00108 } else {
00109 b0 = 0;
00110 b1 = 0;
00111 b2 = 0;
00112 b3 = 0;
00113 }
00114
00115 t = extwl(l, 6);
00116 if (t) {
00117 t = sextw(t);
00118 b0 += W3 * t;
00119 b1 -= W7 * t;
00120 b2 -= W1 * t;
00121 b3 -= W5 * t;
00122 }
00123
00124
00125 t = extwl(r, 2);
00126 if (t) {
00127 t = sextw(t);
00128 b0 += W5 * t;
00129 b1 -= W1 * t;
00130 b2 += W7 * t;
00131 b3 += W3 * t;
00132 }
00133
00134 t = extwl(r, 6);
00135 if (t) {
00136 t = sextw(t);
00137 b0 += W7 * t;
00138 b1 -= W5 * t;
00139 b2 += W3 * t;
00140 b3 -= W1 * t;
00141 }
00142
00143 row[0] = (a0 + b0) >> ROW_SHIFT;
00144 row[1] = (a1 + b1) >> ROW_SHIFT;
00145 row[2] = (a2 + b2) >> ROW_SHIFT;
00146 row[3] = (a3 + b3) >> ROW_SHIFT;
00147 row[4] = (a3 - b3) >> ROW_SHIFT;
00148 row[5] = (a2 - b2) >> ROW_SHIFT;
00149 row[6] = (a1 - b1) >> ROW_SHIFT;
00150 row[7] = (a0 - b0) >> ROW_SHIFT;
00151
00152 return 2;
00153 }
00154
00155 static inline void idct_col(DCTELEM *col)
00156 {
00157 int a0, a1, a2, a3, b0, b1, b2, b3;
00158
00159 col[0] += (1 << (COL_SHIFT - 1)) / W4;
00160
00161 a0 = W4 * col[8 * 0];
00162 a1 = W4 * col[8 * 0];
00163 a2 = W4 * col[8 * 0];
00164 a3 = W4 * col[8 * 0];
00165
00166 if (col[8 * 2]) {
00167 a0 += W2 * col[8 * 2];
00168 a1 += W6 * col[8 * 2];
00169 a2 -= W6 * col[8 * 2];
00170 a3 -= W2 * col[8 * 2];
00171 }
00172
00173 if (col[8 * 4]) {
00174 a0 += W4 * col[8 * 4];
00175 a1 -= W4 * col[8 * 4];
00176 a2 -= W4 * col[8 * 4];
00177 a3 += W4 * col[8 * 4];
00178 }
00179
00180 if (col[8 * 6]) {
00181 a0 += W6 * col[8 * 6];
00182 a1 -= W2 * col[8 * 6];
00183 a2 += W2 * col[8 * 6];
00184 a3 -= W6 * col[8 * 6];
00185 }
00186
00187 if (col[8 * 1]) {
00188 b0 = W1 * col[8 * 1];
00189 b1 = W3 * col[8 * 1];
00190 b2 = W5 * col[8 * 1];
00191 b3 = W7 * col[8 * 1];
00192 } else {
00193 b0 = 0;
00194 b1 = 0;
00195 b2 = 0;
00196 b3 = 0;
00197 }
00198
00199 if (col[8 * 3]) {
00200 b0 += W3 * col[8 * 3];
00201 b1 -= W7 * col[8 * 3];
00202 b2 -= W1 * col[8 * 3];
00203 b3 -= W5 * col[8 * 3];
00204 }
00205
00206 if (col[8 * 5]) {
00207 b0 += W5 * col[8 * 5];
00208 b1 -= W1 * col[8 * 5];
00209 b2 += W7 * col[8 * 5];
00210 b3 += W3 * col[8 * 5];
00211 }
00212
00213 if (col[8 * 7]) {
00214 b0 += W7 * col[8 * 7];
00215 b1 -= W5 * col[8 * 7];
00216 b2 += W3 * col[8 * 7];
00217 b3 -= W1 * col[8 * 7];
00218 }
00219
00220 col[8 * 0] = (a0 + b0) >> COL_SHIFT;
00221 col[8 * 7] = (a0 - b0) >> COL_SHIFT;
00222 col[8 * 1] = (a1 + b1) >> COL_SHIFT;
00223 col[8 * 6] = (a1 - b1) >> COL_SHIFT;
00224 col[8 * 2] = (a2 + b2) >> COL_SHIFT;
00225 col[8 * 5] = (a2 - b2) >> COL_SHIFT;
00226 col[8 * 3] = (a3 + b3) >> COL_SHIFT;
00227 col[8 * 4] = (a3 - b3) >> COL_SHIFT;
00228 }
00229
00230
00231
00232 static inline void idct_col2(DCTELEM *col)
00233 {
00234 int i;
00235 uint64_t l, r;
00236
00237 for (i = 0; i < 8; ++i) {
00238 int a0 = col[i] + (1 << (COL_SHIFT - 1)) / W4;
00239
00240 a0 *= W4;
00241 col[i] = a0 >> COL_SHIFT;
00242 }
00243
00244 l = ldq(col + 0 * 4); r = ldq(col + 1 * 4);
00245 stq(l, col + 2 * 4); stq(r, col + 3 * 4);
00246 stq(l, col + 4 * 4); stq(r, col + 5 * 4);
00247 stq(l, col + 6 * 4); stq(r, col + 7 * 4);
00248 stq(l, col + 8 * 4); stq(r, col + 9 * 4);
00249 stq(l, col + 10 * 4); stq(r, col + 11 * 4);
00250 stq(l, col + 12 * 4); stq(r, col + 13 * 4);
00251 stq(l, col + 14 * 4); stq(r, col + 15 * 4);
00252 }
00253
00254 void ff_simple_idct_axp(DCTELEM *block)
00255 {
00256
00257 int i;
00258 int rowsZero = 1;
00259 int rowsConstant = 1;
00260
00261 for (i = 0; i < 8; i++) {
00262 int sparseness = idct_row(block + 8 * i);
00263
00264 if (i > 0 && sparseness > 0)
00265 rowsZero = 0;
00266 if (sparseness == 2)
00267 rowsConstant = 0;
00268 }
00269
00270 if (rowsZero) {
00271 idct_col2(block);
00272 } else if (rowsConstant) {
00273 idct_col(block);
00274 for (i = 0; i < 8; i += 2) {
00275 uint64_t v = (uint16_t) block[0];
00276 uint64_t w = (uint16_t) block[8];
00277
00278 v |= v << 16;
00279 w |= w << 16;
00280 v |= v << 32;
00281 w |= w << 32;
00282 stq(v, block + 0 * 4);
00283 stq(v, block + 1 * 4);
00284 stq(w, block + 2 * 4);
00285 stq(w, block + 3 * 4);
00286 block += 4 * 4;
00287 }
00288 } else {
00289 for (i = 0; i < 8; i++)
00290 idct_col(block + i);
00291 }
00292 }
00293
00294 void ff_simple_idct_put_axp(uint8_t *dest, int line_size, DCTELEM *block)
00295 {
00296 ff_simple_idct_axp(block);
00297 put_pixels_clamped_axp_p(block, dest, line_size);
00298 }
00299
00300 void ff_simple_idct_add_axp(uint8_t *dest, int line_size, DCTELEM *block)
00301 {
00302 ff_simple_idct_axp(block);
00303 add_pixels_clamped_axp_p(block, dest, line_size);
00304 }