FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
xvid_c_idct.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * XVID MPEG-4 VIDEO CODEC
4  * - Inverse DCT -
5  *
6  * Copyright (C) 2006-2011 Xvid Solutions GmbH
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  *
25  ****************************************************************************/
26 
27 /**
28  * @file
29  * Walken IDCT
30  * Alternative idct implementations for decoding compatibility
31  *
32  * @author Skal
33  * @note this "C" version is not the original one, but is modified to
34  * yield the same error profile as the MMX version.
35  */
36 
37 
38 #include "xvididct.h"
39 
40 
41 #define ROW_SHIFT 11
42 #define COL_SHIFT 6
43 
44 // #define FIX(x) (int)((x) * (1<<ROW_SHIFT))
45 #define Rnd0 65536 // 1<<(COL_SHIFT+ROW_SHIFT-1);
46 #define Rnd1 3597 // FIX (1.75683487303);
47 #define Rnd2 2260 // FIX (1.10355339059);
48 #define Rnd3 1203 // FIX (0.587788325588);
49 #define Rnd4 0
50 #define Rnd5 120 // FIX (0.058658283817);
51 #define Rnd6 512 // FIX (0.25);
52 #define Rnd7 512 // FIX (0.25);
53 
54 static const int Tab04[] = { 22725, 21407, 19266, 16384, 12873, 8867, 4520 };
55 static const int Tab17[] = { 31521, 29692, 26722, 22725, 17855, 12299, 6270 };
56 static const int Tab26[] = { 29692, 27969, 25172, 21407, 16819, 11585, 5906 };
57 static const int Tab35[] = { 26722, 25172, 22654, 19266, 15137, 10426, 5315 };
58 
59 static int Idct_Row(short * In, const int * const Tab, int Rnd)
60 {
61  const int C1 = Tab[0];
62  const int C2 = Tab[1];
63  const int C3 = Tab[2];
64  const int C4 = Tab[3];
65  const int C5 = Tab[4];
66  const int C6 = Tab[5];
67  const int C7 = Tab[6];
68 
69  const int Right = In[5]|In[6]|In[7];
70  const int Left = In[1]|In[2]|In[3];
71  if (!(Right | In[4]))
72  {
73  const int K = C4*In[0] + Rnd;
74  if (Left)
75  {
76  const int a0 = K + C2*In[2];
77  const int a1 = K + C6*In[2];
78  const int a2 = K - C6*In[2];
79  const int a3 = K - C2*In[2];
80 
81  const int b0 = C1*In[1] + C3*In[3];
82  const int b1 = C3*In[1] - C7*In[3];
83  const int b2 = C5*In[1] - C1*In[3];
84  const int b3 = C7*In[1] - C5*In[3];
85 
86  In[0] = (a0 + b0) >> ROW_SHIFT;
87  In[1] = (a1 + b1) >> ROW_SHIFT;
88  In[2] = (a2 + b2) >> ROW_SHIFT;
89  In[3] = (a3 + b3) >> ROW_SHIFT;
90  In[4] = (a3 - b3) >> ROW_SHIFT;
91  In[5] = (a2 - b2) >> ROW_SHIFT;
92  In[6] = (a1 - b1) >> ROW_SHIFT;
93  In[7] = (a0 - b0) >> ROW_SHIFT;
94  }
95  else
96  {
97  const int a0 = K >> ROW_SHIFT;
98  if (a0) {
99  In[0] = In[1] = In[2] = In[3] =
100  In[4] = In[5] = In[6] = In[7] = a0;
101  }
102  else return 0;
103  }
104  }
105  else if (!(Left|Right))
106  {
107  const int a0 = (Rnd + C4*(In[0]+In[4])) >> ROW_SHIFT;
108  const int a1 = (Rnd + C4*(In[0]-In[4])) >> ROW_SHIFT;
109 
110  In[0] = a0;
111  In[3] = a0;
112  In[4] = a0;
113  In[7] = a0;
114  In[1] = a1;
115  In[2] = a1;
116  In[5] = a1;
117  In[6] = a1;
118  }
119  else
120  {
121  const int K = C4*In[0] + Rnd;
122  const int a0 = K + C2*In[2] + C4*In[4] + C6*In[6];
123  const int a1 = K + C6*In[2] - C4*In[4] - C2*In[6];
124  const int a2 = K - C6*In[2] - C4*In[4] + C2*In[6];
125  const int a3 = K - C2*In[2] + C4*In[4] - C6*In[6];
126 
127  const int b0 = C1*In[1] + C3*In[3] + C5*In[5] + C7*In[7];
128  const int b1 = C3*In[1] - C7*In[3] - C1*In[5] - C5*In[7];
129  const int b2 = C5*In[1] - C1*In[3] + C7*In[5] + C3*In[7];
130  const int b3 = C7*In[1] - C5*In[3] + C3*In[5] - C1*In[7];
131 
132  In[0] = (a0 + b0) >> ROW_SHIFT;
133  In[1] = (a1 + b1) >> ROW_SHIFT;
134  In[2] = (a2 + b2) >> ROW_SHIFT;
135  In[3] = (a3 + b3) >> ROW_SHIFT;
136  In[4] = (a3 - b3) >> ROW_SHIFT;
137  In[5] = (a2 - b2) >> ROW_SHIFT;
138  In[6] = (a1 - b1) >> ROW_SHIFT;
139  In[7] = (a0 - b0) >> ROW_SHIFT;
140  }
141  return 1;
142 }
143 
144 #define Tan1 0x32ec
145 #define Tan2 0x6a0a
146 #define Tan3 0xab0e
147 #define Sqrt2 0x5a82
148 
149 #define MULT(c,x, n) ( ((c) * (x)) >> (n) )
150 // 12b version => #define MULT(c,x, n) ( (((c)>>3) * (x)) >> ((n)-3) )
151 // 12b zero-testing version:
152 
153 #define BUTF(a, b, tmp) \
154  (tmp) = (a)+(b); \
155  (b) = (a)-(b); \
156  (a) = (tmp)
157 
158 #define LOAD_BUTF(m1, m2, a, b, tmp, S) \
159  (m1) = (S)[(a)] + (S)[(b)]; \
160  (m2) = (S)[(a)] - (S)[(b)]
161 
162 static void Idct_Col_8(short * const In)
163 {
164  int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, Spill;
165 
166  // odd
167 
168  mm4 = (int)In[7*8];
169  mm5 = (int)In[5*8];
170  mm6 = (int)In[3*8];
171  mm7 = (int)In[1*8];
172 
173  mm0 = MULT(Tan1, mm4, 16) + mm7;
174  mm1 = MULT(Tan1, mm7, 16) - mm4;
175  mm2 = MULT(Tan3, mm5, 16) + mm6;
176  mm3 = MULT(Tan3, mm6, 16) - mm5;
177 
178  mm7 = mm0 + mm2;
179  mm4 = mm1 - mm3;
180  mm0 = mm0 - mm2;
181  mm1 = mm1 + mm3;
182  mm6 = mm0 + mm1;
183  mm5 = mm0 - mm1;
184  mm5 = 2*MULT(Sqrt2, mm5, 16); // 2*sqrt2
185  mm6 = 2*MULT(Sqrt2, mm6, 16); // Watch out: precision loss but done to match
186  // the pmulhw used in mmx/sse versions
187 
188  // even
189 
190  mm1 = (int)In[2*8];
191  mm2 = (int)In[6*8];
192  mm3 = MULT(Tan2,mm2, 16) + mm1;
193  mm2 = MULT(Tan2,mm1, 16) - mm2;
194 
195  LOAD_BUTF(mm0, mm1, 0*8, 4*8, Spill, In);
196 
197  BUTF(mm0, mm3, Spill);
198  BUTF(mm0, mm7, Spill);
199  In[8*0] = (int16_t) (mm0 >> COL_SHIFT);
200  In[8*7] = (int16_t) (mm7 >> COL_SHIFT);
201  BUTF(mm3, mm4, mm0);
202  In[8*3] = (int16_t) (mm3 >> COL_SHIFT);
203  In[8*4] = (int16_t) (mm4 >> COL_SHIFT);
204 
205  BUTF(mm1, mm2, mm0);
206  BUTF(mm1, mm6, mm0);
207  In[8*1] = (int16_t) (mm1 >> COL_SHIFT);
208  In[8*6] = (int16_t) (mm6 >> COL_SHIFT);
209  BUTF(mm2, mm5, mm0);
210  In[8*2] = (int16_t) (mm2 >> COL_SHIFT);
211  In[8*5] = (int16_t) (mm5 >> COL_SHIFT);
212 }
213 
214 static void Idct_Col_4(short * const In)
215 {
216  int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, Spill;
217 
218  // odd
219 
220  mm0 = (int)In[1*8];
221  mm2 = (int)In[3*8];
222 
223  mm1 = MULT(Tan1, mm0, 16);
224  mm3 = MULT(Tan3, mm2, 16);
225 
226  mm7 = mm0 + mm2;
227  mm4 = mm1 - mm3;
228  mm0 = mm0 - mm2;
229  mm1 = mm1 + mm3;
230  mm6 = mm0 + mm1;
231  mm5 = mm0 - mm1;
232  mm6 = 2*MULT(Sqrt2, mm6, 16); // 2*sqrt2
233  mm5 = 2*MULT(Sqrt2, mm5, 16);
234 
235  // even
236 
237  mm0 = mm1 = (int)In[0*8];
238  mm3 = (int)In[2*8];
239  mm2 = MULT(Tan2,mm3, 16);
240 
241  BUTF(mm0, mm3, Spill);
242  BUTF(mm0, mm7, Spill);
243  In[8*0] = (int16_t) (mm0 >> COL_SHIFT);
244  In[8*7] = (int16_t) (mm7 >> COL_SHIFT);
245  BUTF(mm3, mm4, mm0);
246  In[8*3] = (int16_t) (mm3 >> COL_SHIFT);
247  In[8*4] = (int16_t) (mm4 >> COL_SHIFT);
248 
249  BUTF(mm1, mm2, mm0);
250  BUTF(mm1, mm6, mm0);
251  In[8*1] = (int16_t) (mm1 >> COL_SHIFT);
252  In[8*6] = (int16_t) (mm6 >> COL_SHIFT);
253  BUTF(mm2, mm5, mm0);
254  In[8*2] = (int16_t) (mm2 >> COL_SHIFT);
255  In[8*5] = (int16_t) (mm5 >> COL_SHIFT);
256 }
257 
258 static void Idct_Col_3(short * const In)
259 {
260  int mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, Spill;
261 
262  // odd
263 
264  mm7 = (int)In[1*8];
265  mm4 = MULT(Tan1, mm7, 16);
266 
267  mm6 = mm7 + mm4;
268  mm5 = mm7 - mm4;
269  mm6 = 2*MULT(Sqrt2, mm6, 16); // 2*sqrt2
270  mm5 = 2*MULT(Sqrt2, mm5, 16);
271 
272  // even
273 
274  mm0 = mm1 = (int)In[0*8];
275  mm3 = (int)In[2*8];
276  mm2 = MULT(Tan2,mm3, 16);
277 
278  BUTF(mm0, mm3, Spill);
279  BUTF(mm0, mm7, Spill);
280  In[8*0] = (int16_t) (mm0 >> COL_SHIFT);
281  In[8*7] = (int16_t) (mm7 >> COL_SHIFT);
282  BUTF(mm3, mm4, mm0);
283  In[8*3] = (int16_t) (mm3 >> COL_SHIFT);
284  In[8*4] = (int16_t) (mm4 >> COL_SHIFT);
285 
286  BUTF(mm1, mm2, mm0);
287  BUTF(mm1, mm6, mm0);
288  In[8*1] = (int16_t) (mm1 >> COL_SHIFT);
289  In[8*6] = (int16_t) (mm6 >> COL_SHIFT);
290  BUTF(mm2, mm5, mm0);
291  In[8*2] = (int16_t) (mm2 >> COL_SHIFT);
292  In[8*5] = (int16_t) (mm5 >> COL_SHIFT);
293 }
294 
295 #undef Tan1
296 #undef Tan2
297 #undef Tan3
298 #undef Sqrt2
299 
300 #undef ROW_SHIFT
301 #undef COL_SHIFT
302 
303 //////////////////////////////////////////////////////////
304 
305 void ff_idct_xvid(int16_t *const In)
306 {
307  int i, Rows = 0x07;
308 
309  Idct_Row(In + 0*8, Tab04, Rnd0);
310  Idct_Row(In + 1*8, Tab17, Rnd1);
311  Idct_Row(In + 2*8, Tab26, Rnd2);
312  if (Idct_Row(In + 3*8, Tab35, Rnd3)) Rows |= 0x08;
313  if (Idct_Row(In + 4*8, Tab04, Rnd4)) Rows |= 0x10;
314  if (Idct_Row(In + 5*8, Tab35, Rnd5)) Rows |= 0x20;
315  if (Idct_Row(In + 6*8, Tab26, Rnd6)) Rows |= 0x40;
316  if (Idct_Row(In + 7*8, Tab17, Rnd7)) Rows |= 0x80;
317 
318  if (Rows&0xf0) {
319  for(i=0; i<8; i++)
320  Idct_Col_8(In + i);
321  }
322  else if (Rows&0x08) {
323  for(i=0; i<8; i++)
324  Idct_Col_4(In + i);
325  }
326  else {
327  for(i=0; i<8; i++)
328  Idct_Col_3(In + i);
329  }
330 }