]> git.sesse.net Git - ffmpeg/blob - postproc/swscale.c
faster bgr16 input
[ffmpeg] / postproc / swscale.c
1 /*
2     Copyright (C) 2001-2002 Michael Niedermayer <michaelni@gmx.at>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19 /*
20   supported Input formats: YV12, I420, IYUV, YUY2, BGR32, BGR24, BGR16, RGB32, RGB24, Y8, Y800
21   supported output formats: YV12, I420, IYUV, BGR15, BGR16, BGR24, BGR32 (grayscale soon too)
22   BGR15/16 support dithering
23   
24   unscaled special converters
25   YV12/I420/IYUV -> BGR15/BGR16/BGR24/BGR32
26   YV12/I420/IYUV -> YV12/I420/IYUV
27   YUY2/BGR15/BGR16/BGR24/BGR32/RGB24/RGB32 -> same format
28   BGR24 -> BGR32 & RGB24 -> RGB32
29   BGR32 -> BGR24 & RGB32 -> RGB24
30 */
31
32 /* 
33 tested special converters
34  YV12/I420 -> BGR16
35  YV12 -> YV12
36
37 untested special converters
38   YV12/I420/IYUV -> BGR15/BGR24/BGR32 (its the yuv2rgb stuff, so it should be ok)
39   YV12/I420/IYUV -> YV12/I420/IYUV 
40   YUY2/BGR15/BGR16/BGR24/BGR32/RGB24/RGB32 -> same format
41   BGR24 -> BGR32 & RGB24 -> RGB32
42   BGR32 -> BGR24 & RGB32 -> RGB24
43 */
44
45 #include <inttypes.h>
46 #include <string.h>
47 #include <math.h>
48 #include <stdio.h>
49 #include "../config.h"
50 #include "../mangle.h"
51 #ifdef HAVE_MALLOC_H
52 #include <malloc.h>
53 #endif
54 #include "swscale.h"
55 #include "../cpudetect.h"
56 #include "../bswap.h"
57 #include "../libvo/img_format.h"
58 #include "rgb2rgb.h"
59 #undef MOVNTQ
60 #undef PAVGB
61
62 //#undef HAVE_MMX2
63 //#define HAVE_3DNOW
64 //#undef HAVE_MMX
65 //#undef ARCH_X86
66 #define DITHER1XBPP
67
68 #define RET 0xC3 //near return opcode for X86
69
70 #ifdef MP_DEBUG
71 #define ASSERT(x) if(!(x)) { printf("ASSERT " #x " failed\n"); *((int*)0)=0; }
72 #else
73 #define ASSERT(x) ;
74 #endif
75
76 #ifdef M_PI
77 #define PI M_PI
78 #else
79 #define PI 3.14159265358979323846
80 #endif
81
82 //FIXME replace this with something faster
83 #define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420)
84 #define isYUV(x)       ((x)==IMGFMT_YUY2 || isPlanarYUV(x))
85 #define isHalfChrV(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420)
86 #define isHalfChrH(x)  ((x)==IMGFMT_YUY2 || (x)==IMGFMT_YV12 || (x)==IMGFMT_I420)
87 #define isPacked(x)    ((x)==IMGFMT_YUY2 || ((x)&IMGFMT_BGR_MASK)==IMGFMT_BGR || ((x)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
88 #define isGray(x)      ((x)==IMGFMT_Y800)
89 #define isSupportedIn(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YUY2 \
90                         || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16\
91                         || (x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24\
92                         || (x)==IMGFMT_Y800)
93 #define isSupportedOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 \
94                         || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15)
95 #define isBGR(x)       ((x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15)
96
97 #define RGB2YUV_SHIFT 16
98 #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
99 #define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
100 #define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
101 #define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
102 #define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
103 #define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
104 #define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
105 #define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
106 #define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
107
108 extern int verbose; // defined in mplayer.c
109 /*
110 NOTES
111
112 known BUGS with known cause (no bugreports please!, but patches are welcome :) )
113 horizontal fast_bilinear MMX2 scaler reads 1-7 samples too much (might cause a sig11)
114
115 Special versions: fast Y 1:1 scaling (no interpolation in y direction)
116
117 TODO
118 more intelligent missalignment avoidance for the horizontal scaler
119 write special vertical cubic upscale version
120 Optimize C code (yv12 / minmax)
121 add support for packed pixel yuv input & output
122 add support for Y8 output
123 optimize bgr24 & bgr32
124 add BGR4 output support
125 write special BGR->BGR scaler
126 deglobalize yuv2rgb*.c
127 */
128
129 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
130 #define MIN(a,b) ((a) > (b) ? (b) : (a))
131 #define MAX(a,b) ((a) < (b) ? (b) : (a))
132
133 #ifdef ARCH_X86
134 #define CAN_COMPILE_X86_ASM
135 #endif
136
137 #ifdef CAN_COMPILE_X86_ASM
138 static uint64_t __attribute__((aligned(8))) yCoeff=    0x2568256825682568LL;
139 static uint64_t __attribute__((aligned(8))) vrCoeff=   0x3343334333433343LL;
140 static uint64_t __attribute__((aligned(8))) ubCoeff=   0x40cf40cf40cf40cfLL;
141 static uint64_t __attribute__((aligned(8))) vgCoeff=   0xE5E2E5E2E5E2E5E2LL;
142 static uint64_t __attribute__((aligned(8))) ugCoeff=   0xF36EF36EF36EF36ELL;
143 static uint64_t __attribute__((aligned(8))) bF8=       0xF8F8F8F8F8F8F8F8LL;
144 static uint64_t __attribute__((aligned(8))) bFC=       0xFCFCFCFCFCFCFCFCLL;
145 static uint64_t __attribute__((aligned(8))) w400=      0x0400040004000400LL;
146 static uint64_t __attribute__((aligned(8))) w80=       0x0080008000800080LL;
147 static uint64_t __attribute__((aligned(8))) w10=       0x0010001000100010LL;
148 static uint64_t __attribute__((aligned(8))) w02=       0x0002000200020002LL;
149 static uint64_t __attribute__((aligned(8))) bm00001111=0x00000000FFFFFFFFLL;
150 static uint64_t __attribute__((aligned(8))) bm00000111=0x0000000000FFFFFFLL;
151 static uint64_t __attribute__((aligned(8))) bm11111000=0xFFFFFFFFFF000000LL;
152 static uint64_t __attribute__((aligned(8))) bm01010101=0x00FF00FF00FF00FFLL;
153
154 static volatile uint64_t __attribute__((aligned(8))) b5Dither;
155 static volatile uint64_t __attribute__((aligned(8))) g5Dither;
156 static volatile uint64_t __attribute__((aligned(8))) g6Dither;
157 static volatile uint64_t __attribute__((aligned(8))) r5Dither;
158
159 static uint64_t __attribute__((aligned(8))) dither4[2]={
160         0x0103010301030103LL,
161         0x0200020002000200LL,};
162
163 static uint64_t __attribute__((aligned(8))) dither8[2]={
164         0x0602060206020602LL,
165         0x0004000400040004LL,};
166
167 static uint64_t __attribute__((aligned(8))) b16Mask=   0x001F001F001F001FLL;
168 static uint64_t __attribute__((aligned(8))) g16Mask=   0x07E007E007E007E0LL;
169 static uint64_t __attribute__((aligned(8))) r16Mask=   0xF800F800F800F800LL;
170 static uint64_t __attribute__((aligned(8))) b15Mask=   0x001F001F001F001FLL;
171 static uint64_t __attribute__((aligned(8))) g15Mask=   0x03E003E003E003E0LL;
172 static uint64_t __attribute__((aligned(8))) r15Mask=   0x7C007C007C007C00LL;
173
174 static uint64_t __attribute__((aligned(8))) M24A=   0x00FF0000FF0000FFLL;
175 static uint64_t __attribute__((aligned(8))) M24B=   0xFF0000FF0000FF00LL;
176 static uint64_t __attribute__((aligned(8))) M24C=   0x0000FF0000FF0000LL;
177
178 // FIXME remove
179 static uint64_t __attribute__((aligned(8))) asm_yalpha1;
180 static uint64_t __attribute__((aligned(8))) asm_uvalpha1;
181 #endif
182
183 // clipping helper table for C implementations:
184 static unsigned char clip_table[768];
185
186 static unsigned short clip_table16b[768];
187 static unsigned short clip_table16g[768];
188 static unsigned short clip_table16r[768];
189 static unsigned short clip_table15b[768];
190 static unsigned short clip_table15g[768];
191 static unsigned short clip_table15r[768];
192
193 // yuv->rgb conversion tables:
194 static    int yuvtab_2568[256];
195 static    int yuvtab_3343[256];
196 static    int yuvtab_0c92[256];
197 static    int yuvtab_1a1e[256];
198 static    int yuvtab_40cf[256];
199 // Needed for cubic scaler to catch overflows
200 static    int clip_yuvtab_2568[768];
201 static    int clip_yuvtab_3343[768];
202 static    int clip_yuvtab_0c92[768];
203 static    int clip_yuvtab_1a1e[768];
204 static    int clip_yuvtab_40cf[768];
205
206 //global sws_flags from the command line
207 int sws_flags=2;
208
209 //global srcFilter
210 SwsFilter src_filter= {NULL, NULL, NULL, NULL};
211
212 float sws_lum_gblur= 0.0;
213 float sws_chr_gblur= 0.0;
214 int sws_chr_vshift= 0;
215 int sws_chr_hshift= 0;
216 float sws_chr_sharpen= 0.0;
217 float sws_lum_sharpen= 0.0;
218
219 /* cpuCaps combined from cpudetect and whats actually compiled in
220    (if there is no support for something compiled in it wont appear here) */
221 static CpuCaps cpuCaps;
222
223 void (*swScale)(SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,
224              int srcSliceH, uint8_t* dst[], int dstStride[])=NULL;
225
226 static SwsVector *getConvVec(SwsVector *a, SwsVector *b);
227
228 #ifdef CAN_COMPILE_X86_ASM
229 void in_asm_used_var_warning_killer()
230 {
231  volatile int i= yCoeff+vrCoeff+ubCoeff+vgCoeff+ugCoeff+bF8+bFC+w400+w80+w10+
232  bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+asm_yalpha1+ asm_uvalpha1+
233  M24A+M24B+M24C+w02 + b5Dither+g5Dither+r5Dither+g6Dither+dither4[0]+dither8[0]+bm01010101;
234  if(i) i=0;
235 }
236 #endif
237
238 static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
239                                     int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
240                                     uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW)
241 {
242         //FIXME Optimize (just quickly writen not opti..)
243         int i;
244         for(i=0; i<dstW; i++)
245         {
246                 int val=0;
247                 int j;
248                 for(j=0; j<lumFilterSize; j++)
249                         val += lumSrc[j][i] * lumFilter[j];
250
251                 dest[i]= MIN(MAX(val>>19, 0), 255);
252         }
253
254         if(uDest != NULL)
255                 for(i=0; i<(dstW>>1); i++)
256                 {
257                         int u=0;
258                         int v=0;
259                         int j;
260                         for(j=0; j<chrFilterSize; j++)
261                         {
262                                 u += chrSrc[j][i] * chrFilter[j];
263                                 v += chrSrc[j][i + 2048] * chrFilter[j];
264                         }
265
266                         uDest[i]= MIN(MAX(u>>19, 0), 255);
267                         vDest[i]= MIN(MAX(v>>19, 0), 255);
268                 }
269 }
270
271 static inline void yuv2rgbXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
272                                     int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
273                                     uint8_t *dest, int dstW, int dstFormat)
274 {
275         if(dstFormat==IMGFMT_BGR32)
276         {
277                 int i;
278                 for(i=0; i<(dstW>>1); i++){
279                         int j;
280                         int Y1=0;
281                         int Y2=0;
282                         int U=0;
283                         int V=0;
284                         int Cb, Cr, Cg;
285                         for(j=0; j<lumFilterSize; j++)
286                         {
287                                 Y1 += lumSrc[j][2*i] * lumFilter[j];
288                                 Y2 += lumSrc[j][2*i+1] * lumFilter[j];
289                         }
290                         for(j=0; j<chrFilterSize; j++)
291                         {
292                                 U += chrSrc[j][i] * chrFilter[j];
293                                 V += chrSrc[j][i+2048] * chrFilter[j];
294                         }
295                         Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
296                         Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
297                         U >>= 19;
298                         V >>= 19;
299
300                         Cb= clip_yuvtab_40cf[U+ 256];
301                         Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
302                         Cr= clip_yuvtab_3343[V+ 256];
303
304                         dest[8*i+0]=clip_table[((Y1 + Cb) >>13)];
305                         dest[8*i+1]=clip_table[((Y1 + Cg) >>13)];
306                         dest[8*i+2]=clip_table[((Y1 + Cr) >>13)];
307
308                         dest[8*i+4]=clip_table[((Y2 + Cb) >>13)];
309                         dest[8*i+5]=clip_table[((Y2 + Cg) >>13)];
310                         dest[8*i+6]=clip_table[((Y2 + Cr) >>13)];
311                 }
312         }
313         else if(dstFormat==IMGFMT_BGR24)
314         {
315                 int i;
316                 for(i=0; i<(dstW>>1); i++){
317                         int j;
318                         int Y1=0;
319                         int Y2=0;
320                         int U=0;
321                         int V=0;
322                         int Cb, Cr, Cg;
323                         for(j=0; j<lumFilterSize; j++)
324                         {
325                                 Y1 += lumSrc[j][2*i] * lumFilter[j];
326                                 Y2 += lumSrc[j][2*i+1] * lumFilter[j];
327                         }
328                         for(j=0; j<chrFilterSize; j++)
329                         {
330                                 U += chrSrc[j][i] * chrFilter[j];
331                                 V += chrSrc[j][i+2048] * chrFilter[j];
332                         }
333                         Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
334                         Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
335                         U >>= 19;
336                         V >>= 19;
337
338                         Cb= clip_yuvtab_40cf[U+ 256];
339                         Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
340                         Cr= clip_yuvtab_3343[V+ 256];
341
342                         dest[0]=clip_table[((Y1 + Cb) >>13)];
343                         dest[1]=clip_table[((Y1 + Cg) >>13)];
344                         dest[2]=clip_table[((Y1 + Cr) >>13)];
345
346                         dest[3]=clip_table[((Y2 + Cb) >>13)];
347                         dest[4]=clip_table[((Y2 + Cg) >>13)];
348                         dest[5]=clip_table[((Y2 + Cr) >>13)];
349                         dest+=6;
350                 }
351         }
352         else if(dstFormat==IMGFMT_BGR16)
353         {
354                 int i;
355 #ifdef DITHER1XBPP
356                 static int ditherb1=1<<14;
357                 static int ditherg1=1<<13;
358                 static int ditherr1=2<<14;
359                 static int ditherb2=3<<14;
360                 static int ditherg2=3<<13;
361                 static int ditherr2=0<<14;
362
363                 ditherb1 ^= (1^2)<<14;
364                 ditherg1 ^= (1^2)<<13;
365                 ditherr1 ^= (1^2)<<14;
366                 ditherb2 ^= (3^0)<<14;
367                 ditherg2 ^= (3^0)<<13;
368                 ditherr2 ^= (3^0)<<14;
369 #else
370                 const int ditherb1=0;
371                 const int ditherg1=0;
372                 const int ditherr1=0;
373                 const int ditherb2=0;
374                 const int ditherg2=0;
375                 const int ditherr2=0;
376 #endif
377                 for(i=0; i<(dstW>>1); i++){
378                         int j;
379                         int Y1=0;
380                         int Y2=0;
381                         int U=0;
382                         int V=0;
383                         int Cb, Cr, Cg;
384                         for(j=0; j<lumFilterSize; j++)
385                         {
386                                 Y1 += lumSrc[j][2*i] * lumFilter[j];
387                                 Y2 += lumSrc[j][2*i+1] * lumFilter[j];
388                         }
389                         for(j=0; j<chrFilterSize; j++)
390                         {
391                                 U += chrSrc[j][i] * chrFilter[j];
392                                 V += chrSrc[j][i+2048] * chrFilter[j];
393                         }
394                         Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
395                         Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
396                         U >>= 19;
397                         V >>= 19;
398
399                         Cb= clip_yuvtab_40cf[U+ 256];
400                         Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
401                         Cr= clip_yuvtab_3343[V+ 256];
402
403                         ((uint16_t*)dest)[2*i] =
404                                 clip_table16b[(Y1 + Cb + ditherb1) >>13] |
405                                 clip_table16g[(Y1 + Cg + ditherg1) >>13] |
406                                 clip_table16r[(Y1 + Cr + ditherr1) >>13];
407
408                         ((uint16_t*)dest)[2*i+1] =
409                                 clip_table16b[(Y2 + Cb + ditherb2) >>13] |
410                                 clip_table16g[(Y2 + Cg + ditherg2) >>13] |
411                                 clip_table16r[(Y2 + Cr + ditherr2) >>13];
412                 }
413         }
414         else if(dstFormat==IMGFMT_BGR15)
415         {
416                 int i;
417 #ifdef DITHER1XBPP
418                 static int ditherb1=1<<14;
419                 static int ditherg1=1<<14;
420                 static int ditherr1=2<<14;
421                 static int ditherb2=3<<14;
422                 static int ditherg2=3<<14;
423                 static int ditherr2=0<<14;
424
425                 ditherb1 ^= (1^2)<<14;
426                 ditherg1 ^= (1^2)<<14;
427                 ditherr1 ^= (1^2)<<14;
428                 ditherb2 ^= (3^0)<<14;
429                 ditherg2 ^= (3^0)<<14;
430                 ditherr2 ^= (3^0)<<14;
431 #else
432                 const int ditherb1=0;
433                 const int ditherg1=0;
434                 const int ditherr1=0;
435                 const int ditherb2=0;
436                 const int ditherg2=0;
437                 const int ditherr2=0;
438 #endif
439                 for(i=0; i<(dstW>>1); i++){
440                         int j;
441                         int Y1=0;
442                         int Y2=0;
443                         int U=0;
444                         int V=0;
445                         int Cb, Cr, Cg;
446                         for(j=0; j<lumFilterSize; j++)
447                         {
448                                 Y1 += lumSrc[j][2*i] * lumFilter[j];
449                                 Y2 += lumSrc[j][2*i+1] * lumFilter[j];
450                         }
451                         for(j=0; j<chrFilterSize; j++)
452                         {
453                                 U += chrSrc[j][i] * chrFilter[j];
454                                 V += chrSrc[j][i+2048] * chrFilter[j];
455                         }
456                         Y1= clip_yuvtab_2568[ (Y1>>19) + 256 ];
457                         Y2= clip_yuvtab_2568[ (Y2>>19) + 256 ];
458                         U >>= 19;
459                         V >>= 19;
460
461                         Cb= clip_yuvtab_40cf[U+ 256];
462                         Cg= clip_yuvtab_1a1e[V+ 256] + yuvtab_0c92[U+ 256];
463                         Cr= clip_yuvtab_3343[V+ 256];
464
465                         ((uint16_t*)dest)[2*i] =
466                                 clip_table15b[(Y1 + Cb + ditherb1) >>13] |
467                                 clip_table15g[(Y1 + Cg + ditherg1) >>13] |
468                                 clip_table15r[(Y1 + Cr + ditherr1) >>13];
469
470                         ((uint16_t*)dest)[2*i+1] =
471                                 clip_table15b[(Y2 + Cb + ditherb2) >>13] |
472                                 clip_table15g[(Y2 + Cg + ditherg2) >>13] |
473                                 clip_table15r[(Y2 + Cr + ditherr2) >>13];
474                 }
475         }
476 }
477
478
479 //Note: we have C, X86, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
480 //Plain C versions
481 #if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT)
482 #define COMPILE_C
483 #endif
484
485 #ifdef CAN_COMPILE_X86_ASM
486
487 #if (defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
488 #define COMPILE_MMX
489 #endif
490
491 #if defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT)
492 #define COMPILE_MMX2
493 #endif
494
495 #if (defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)
496 #define COMPILE_3DNOW
497 #endif
498 #endif //CAN_COMPILE_X86_ASM
499
500 #undef HAVE_MMX
501 #undef HAVE_MMX2
502 #undef HAVE_3DNOW
503
504 #ifdef COMPILE_C
505 #undef HAVE_MMX
506 #undef HAVE_MMX2
507 #undef HAVE_3DNOW
508 #define RENAME(a) a ## _C
509 #include "swscale_template.c"
510 #endif
511
512 #ifdef CAN_COMPILE_X86_ASM
513
514 //X86 versions
515 /*
516 #undef RENAME
517 #undef HAVE_MMX
518 #undef HAVE_MMX2
519 #undef HAVE_3DNOW
520 #define ARCH_X86
521 #define RENAME(a) a ## _X86
522 #include "swscale_template.c"
523 */
524 //MMX versions
525 #ifdef COMPILE_MMX
526 #undef RENAME
527 #define HAVE_MMX
528 #undef HAVE_MMX2
529 #undef HAVE_3DNOW
530 #define RENAME(a) a ## _MMX
531 #include "swscale_template.c"
532 #endif
533
534 //MMX2 versions
535 #ifdef COMPILE_MMX2
536 #undef RENAME
537 #define HAVE_MMX
538 #define HAVE_MMX2
539 #undef HAVE_3DNOW
540 #define RENAME(a) a ## _MMX2
541 #include "swscale_template.c"
542 #endif
543
544 //3DNOW versions
545 #ifdef COMPILE_3DNOW
546 #undef RENAME
547 #define HAVE_MMX
548 #undef HAVE_MMX2
549 #define HAVE_3DNOW
550 #define RENAME(a) a ## _3DNow
551 #include "swscale_template.c"
552 #endif
553
554 #endif //CAN_COMPILE_X86_ASM
555
556 // minor note: the HAVE_xyz is messed up after that line so dont use it
557
558
559 // old global scaler, dont use for new code
560 // will use sws_flags from the command line
561 void SwScale_YV12slice(unsigned char* src[], int srcStride[], int srcSliceY ,
562                              int srcSliceH, uint8_t* dst[], int dstStride, int dstbpp,
563                              int srcW, int srcH, int dstW, int dstH){
564
565         static SwsContext *context=NULL;
566         int dstFormat;
567         int dstStride3[3]= {dstStride, dstStride>>1, dstStride>>1};
568
569         switch(dstbpp)
570         {
571                 case 8 : dstFormat= IMGFMT_Y8;          break;
572                 case 12: dstFormat= IMGFMT_YV12;        break;
573                 case 15: dstFormat= IMGFMT_BGR15;       break;
574                 case 16: dstFormat= IMGFMT_BGR16;       break;
575                 case 24: dstFormat= IMGFMT_BGR24;       break;
576                 case 32: dstFormat= IMGFMT_BGR32;       break;
577                 default: return;
578         }
579
580         if(!context) context=getSwsContextFromCmdLine(srcW, srcH, IMGFMT_YV12, dstW, dstH, dstFormat);
581
582         context->swScale(context, src, srcStride, srcSliceY, srcSliceH, dst, dstStride3);
583 }
584
585 // will use sws_flags & src_filter (from cmd line)
586 SwsContext *getSwsContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
587 {
588         int flags=0;
589         static int firstTime=1;
590
591 #ifdef ARCH_X86
592         if(gCpuCaps.hasMMX)
593                 asm volatile("emms\n\t"::: "memory"); //FIXME this shouldnt be required but it IS (even for non mmx versions)
594 #endif
595         if(firstTime)
596         {
597                 firstTime=0;
598                 flags= SWS_PRINT_INFO;
599         }
600         else if(verbose>1) flags= SWS_PRINT_INFO;
601
602         if(src_filter.lumH) freeVec(src_filter.lumH);
603         if(src_filter.lumV) freeVec(src_filter.lumV);
604         if(src_filter.chrH) freeVec(src_filter.chrH);
605         if(src_filter.chrV) freeVec(src_filter.chrV);
606
607         if(sws_lum_gblur!=0.0){
608                 src_filter.lumH= getGaussianVec(sws_lum_gblur, 3.0);
609                 src_filter.lumV= getGaussianVec(sws_lum_gblur, 3.0);
610         }else{
611                 src_filter.lumH= getIdentityVec();
612                 src_filter.lumV= getIdentityVec();
613         }
614
615         if(sws_chr_gblur!=0.0){
616                 src_filter.chrH= getGaussianVec(sws_chr_gblur, 3.0);
617                 src_filter.chrV= getGaussianVec(sws_chr_gblur, 3.0);
618         }else{
619                 src_filter.chrH= getIdentityVec();
620                 src_filter.chrV= getIdentityVec();
621         }
622
623         if(sws_chr_sharpen!=0.0){
624                 SwsVector *g= getConstVec(-1.0, 3);
625                 SwsVector *id= getConstVec(10.0/sws_chr_sharpen, 1);
626                 g->coeff[1]=2.0;
627                 addVec(id, g);
628                 convVec(src_filter.chrH, id);
629                 convVec(src_filter.chrV, id);
630                 freeVec(g);
631                 freeVec(id);
632         }
633
634         if(sws_lum_sharpen!=0.0){
635                 SwsVector *g= getConstVec(-1.0, 3);
636                 SwsVector *id= getConstVec(10.0/sws_lum_sharpen, 1);
637                 g->coeff[1]=2.0;
638                 addVec(id, g);
639                 convVec(src_filter.lumH, id);
640                 convVec(src_filter.lumV, id);
641                 freeVec(g);
642                 freeVec(id);
643         }
644
645         if(sws_chr_hshift)
646                 shiftVec(src_filter.chrH, sws_chr_hshift);
647
648         if(sws_chr_vshift)
649                 shiftVec(src_filter.chrV, sws_chr_vshift);
650
651         normalizeVec(src_filter.chrH, 1.0);
652         normalizeVec(src_filter.chrV, 1.0);
653         normalizeVec(src_filter.lumH, 1.0);
654         normalizeVec(src_filter.lumV, 1.0);
655
656         if(verbose > 1) printVec(src_filter.chrH);
657         if(verbose > 1) printVec(src_filter.lumH);
658
659         switch(sws_flags)
660         {
661                 case 0: flags|= SWS_FAST_BILINEAR; break;
662                 case 1: flags|= SWS_BILINEAR; break;
663                 case 2: flags|= SWS_BICUBIC; break;
664                 case 3: flags|= SWS_X; break;
665                 case 4: flags|= SWS_POINT; break;
666                 case 5: flags|= SWS_AREA; break;
667                 default:flags|= SWS_BILINEAR; break;
668         }
669
670         return getSwsContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, &src_filter, NULL);
671 }
672
673
674 static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc,
675                               int srcW, int dstW, int filterAlign, int one, int flags,
676                               SwsVector *srcFilter, SwsVector *dstFilter)
677 {
678         int i;
679         int filterSize;
680         int filter2Size;
681         int minFilterSize;
682         double *filter=NULL;
683         double *filter2=NULL;
684 #ifdef ARCH_X86
685         if(gCpuCaps.hasMMX)
686                 asm volatile("emms\n\t"::: "memory"); //FIXME this shouldnt be required but it IS (even for non mmx versions)
687 #endif
688
689         // Note the +1 is for the MMXscaler which reads over the end
690         *filterPos = (int16_t*)memalign(8, (dstW+1)*sizeof(int16_t));
691
692         if(ABS(xInc - 0x10000) <10) // unscaled
693         {
694                 int i;
695                 filterSize= 1;
696                 filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
697                 for(i=0; i<dstW*filterSize; i++) filter[i]=0;
698
699                 for(i=0; i<dstW; i++)
700                 {
701                         filter[i*filterSize]=1;
702                         (*filterPos)[i]=i;
703                 }
704
705         }
706         else if(flags&SWS_POINT) // lame looking point sampling mode
707         {
708                 int i;
709                 int xDstInSrc;
710                 filterSize= 1;
711                 filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
712                 
713                 xDstInSrc= xInc/2 - 0x8000;
714                 for(i=0; i<dstW; i++)
715                 {
716                         int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
717
718                         (*filterPos)[i]= xx;
719                         filter[i]= 1.0;
720                         xDstInSrc+= xInc;
721                 }
722         }
723         else if(xInc <= (1<<16) || (flags&SWS_FAST_BILINEAR)) // upscale
724         {
725                 int i;
726                 int xDstInSrc;
727                 if     (flags&SWS_BICUBIC) filterSize= 4;
728                 else if(flags&SWS_X      ) filterSize= 4;
729                 else                       filterSize= 2; // SWS_BILINEAR / SWS_AREA 
730 //              printf("%d %d %d\n", filterSize, srcW, dstW);
731                 filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
732
733                 xDstInSrc= xInc/2 - 0x8000;
734                 for(i=0; i<dstW; i++)
735                 {
736                         int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16;
737                         int j;
738
739                         (*filterPos)[i]= xx;
740                         if((flags & SWS_BICUBIC) || (flags & SWS_X))
741                         {
742                                 double d= ABS(((xx+1)<<16) - xDstInSrc)/(double)(1<<16);
743                                 double y1,y2,y3,y4;
744                                 double A= -0.6;
745                                 if(flags & SWS_BICUBIC){
746                                                 // Equation is from VirtualDub
747                                         y1 = (        +     A*d -       2.0*A*d*d +       A*d*d*d);
748                                         y2 = (+ 1.0             -     (A+3.0)*d*d + (A+2.0)*d*d*d);
749                                         y3 = (        -     A*d + (2.0*A+3.0)*d*d - (A+2.0)*d*d*d);
750                                         y4 = (                  +           A*d*d -       A*d*d*d);
751                                 }else{
752                                                 // cubic interpolation (derived it myself)
753                                         y1 = (    -2.0*d + 3.0*d*d - 1.0*d*d*d)/6.0;
754                                         y2 = (6.0 -3.0*d - 6.0*d*d + 3.0*d*d*d)/6.0;
755                                         y3 = (    +6.0*d + 3.0*d*d - 3.0*d*d*d)/6.0;
756                                         y4 = (    -1.0*d           + 1.0*d*d*d)/6.0;
757                                 }
758
759 //                              printf("%d %d %d \n", coeff, (int)d, xDstInSrc);
760                                 filter[i*filterSize + 0]= y1;
761                                 filter[i*filterSize + 1]= y2;
762                                 filter[i*filterSize + 2]= y3;
763                                 filter[i*filterSize + 3]= y4;
764 //                              printf("%1.3f %1.3f %1.3f %1.3f %1.3f\n",d , y1, y2, y3, y4);
765                         }
766                         else
767                         {
768                                 //Bilinear upscale / linear interpolate / Area averaging
769                                 for(j=0; j<filterSize; j++)
770                                 {
771                                         double d= ABS((xx<<16) - xDstInSrc)/(double)(1<<16);
772                                         double coeff= 1.0 - d;
773                                         if(coeff<0) coeff=0;
774         //                              printf("%d %d %d \n", coeff, (int)d, xDstInSrc);
775                                         filter[i*filterSize + j]= coeff;
776                                         xx++;
777                                 }
778                         }
779                         xDstInSrc+= xInc;
780                 }
781         }
782         else // downscale
783         {
784                 int xDstInSrc;
785                 if(flags&SWS_BICUBIC)   filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
786                 else if(flags&SWS_X)    filterSize= (int)ceil(1 + 4.0*srcW / (double)dstW);
787                 else if(flags&SWS_AREA) filterSize= (int)ceil(1 + 1.0*srcW / (double)dstW);
788                 else /* BILINEAR */     filterSize= (int)ceil(1 + 2.0*srcW / (double)dstW);
789 //              printf("%d %d %d\n", *filterSize, srcW, dstW);
790                 filter= (double*)memalign(8, dstW*sizeof(double)*filterSize);
791
792                 xDstInSrc= xInc/2 - 0x8000;
793                 for(i=0; i<dstW; i++)
794                 {
795                         int xx= (int)((double)xDstInSrc/(double)(1<<16) - (filterSize-1)*0.5 + 0.5);
796                         int j;
797                         (*filterPos)[i]= xx;
798                         for(j=0; j<filterSize; j++)
799                         {
800                                 double d= ABS((xx<<16) - xDstInSrc)/(double)xInc;
801                                 double coeff;
802                                 if((flags & SWS_BICUBIC) || (flags & SWS_X))
803                                 {
804                                         double A= -0.75;
805 //                                      d*=2;
806                                         // Equation is from VirtualDub
807                                         if(d<1.0)
808                                                 coeff = (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d);
809                                         else if(d<2.0)
810                                                 coeff = (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d);
811                                         else
812                                                 coeff=0.0;
813                                 }
814                                 else if(flags & SWS_AREA)
815                                 {
816                                         double srcPixelSize= (1<<16)/(double)xInc;
817                                         if(d + srcPixelSize/2 < 0.5) coeff= 1.0;
818                                         else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5;
819                                         else coeff=0.0;
820                                 }
821                                 else
822                                 {
823                                         coeff= 1.0 - d;
824                                         if(coeff<0) coeff=0;
825                                 }
826 //                              printf("%1.3f %2.3f %d \n", coeff, d, xDstInSrc);
827                                 filter[i*filterSize + j]= coeff;
828                                 xx++;
829                         }
830                         xDstInSrc+= xInc;
831                 }
832         }
833
834         /* apply src & dst Filter to filter -> filter2
835            free(filter);
836         */
837         filter2Size= filterSize;
838         if(srcFilter) filter2Size+= srcFilter->length - 1;
839         if(dstFilter) filter2Size+= dstFilter->length - 1;
840         filter2= (double*)memalign(8, filter2Size*dstW*sizeof(double));
841
842         for(i=0; i<dstW; i++)
843         {
844                 int j;
845                 SwsVector scaleFilter;
846                 SwsVector *outVec;
847
848                 scaleFilter.coeff= filter + i*filterSize;
849                 scaleFilter.length= filterSize;
850
851                 if(srcFilter) outVec= getConvVec(srcFilter, &scaleFilter);
852                 else          outVec= &scaleFilter;
853
854                 ASSERT(outVec->length == filter2Size)
855                 //FIXME dstFilter
856
857                 for(j=0; j<outVec->length; j++)
858                 {
859                         filter2[i*filter2Size + j]= outVec->coeff[j];
860                 }
861
862                 (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2;
863
864                 if(outVec != &scaleFilter) freeVec(outVec);
865         }
866         free(filter); filter=NULL;
867
868         /* try to reduce the filter-size (step1 find size and shift left) */
869         // Assume its near normalized (*0.5 or *2.0 is ok but * 0.001 is not)
870         minFilterSize= 0;
871         for(i=dstW-1; i>=0; i--)
872         {
873                 int min= filter2Size;
874                 int j;
875                 double cutOff=0.0;
876
877                 /* get rid off near zero elements on the left by shifting left */
878                 for(j=0; j<filter2Size; j++)
879                 {
880                         int k;
881                         cutOff += ABS(filter2[i*filter2Size]);
882
883                         if(cutOff > SWS_MAX_REDUCE_CUTOFF) break;
884
885                         /* preserve Monotonicity because the core cant handle the filter otherwise */
886                         if(i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break;
887
888                         // Move filter coeffs left
889                         for(k=1; k<filter2Size; k++)
890                                 filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k];
891                         filter2[i*filter2Size + k - 1]= 0.0;
892                         (*filterPos)[i]++;
893                 }
894
895                 cutOff=0.0;
896                 /* count near zeros on the right */
897                 for(j=filter2Size-1; j>0; j--)
898                 {
899                         cutOff += ABS(filter2[i*filter2Size + j]);
900
901                         if(cutOff > SWS_MAX_REDUCE_CUTOFF) break;
902                         min--;
903                 }
904
905                 if(min>minFilterSize) minFilterSize= min;
906         }
907
908         filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1));
909         filter= (double*)memalign(8, filterSize*dstW*sizeof(double));
910         *outFilterSize= filterSize;
911
912         if((flags&SWS_PRINT_INFO) && verbose)
913                 printf("SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize);
914         /* try to reduce the filter-size (step2 reduce it) */
915         for(i=0; i<dstW; i++)
916         {
917                 int j;
918
919                 for(j=0; j<filterSize; j++)
920                 {
921                         if(j>=filter2Size) filter[i*filterSize + j]= 0.0;
922                         else               filter[i*filterSize + j]= filter2[i*filter2Size + j];
923                 }
924         }
925         free(filter2); filter2=NULL;
926         
927         ASSERT(filterSize > 0)
928
929         //FIXME try to align filterpos if possible
930
931         //fix borders
932         for(i=0; i<dstW; i++)
933         {
934                 int j;
935                 if((*filterPos)[i] < 0)
936                 {
937                         // Move filter coeffs left to compensate for filterPos
938                         for(j=1; j<filterSize; j++)
939                         {
940                                 int left= MAX(j + (*filterPos)[i], 0);
941                                 filter[i*filterSize + left] += filter[i*filterSize + j];
942                                 filter[i*filterSize + j]=0;
943                         }
944                         (*filterPos)[i]= 0;
945                 }
946
947                 if((*filterPos)[i] + filterSize > srcW)
948                 {
949                         int shift= (*filterPos)[i] + filterSize - srcW;
950                         // Move filter coeffs right to compensate for filterPos
951                         for(j=filterSize-2; j>=0; j--)
952                         {
953                                 int right= MIN(j + shift, filterSize-1);
954                                 filter[i*filterSize +right] += filter[i*filterSize +j];
955                                 filter[i*filterSize +j]=0;
956                         }
957                         (*filterPos)[i]= srcW - filterSize;
958                 }
959         }
960
961         // Note the +1 is for the MMXscaler which reads over the end
962         *outFilter= (int16_t*)memalign(8, *outFilterSize*(dstW+1)*sizeof(int16_t));
963         memset(*outFilter, 0, *outFilterSize*(dstW+1)*sizeof(int16_t));
964
965         /* Normalize & Store in outFilter */
966         for(i=0; i<dstW; i++)
967         {
968                 int j;
969                 double sum=0;
970                 double scale= one;
971                 for(j=0; j<filterSize; j++)
972                 {
973                         sum+= filter[i*filterSize + j];
974                 }
975                 scale/= sum;
976                 for(j=0; j<filterSize; j++)
977                 {
978                         (*outFilter)[i*(*outFilterSize) + j]= (int)(filter[i*filterSize + j]*scale);
979                 }
980         }
981         
982         (*filterPos)[dstW]= (*filterPos)[dstW-1]; // the MMX scaler will read over the end
983         for(i=0; i<*outFilterSize; i++)
984         {
985                 int j= dstW*(*outFilterSize);
986                 (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)];
987         }
988
989         free(filter);
990 }
991
992 #ifdef ARCH_X86
993 static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode)
994 {
995         uint8_t *fragment;
996         int imm8OfPShufW1;
997         int imm8OfPShufW2;
998         int fragmentLength;
999
1000         int xpos, i;
1001
1002         // create an optimized horizontal scaling routine
1003
1004         //code fragment
1005
1006         asm volatile(
1007                 "jmp 9f                         \n\t"
1008         // Begin
1009                 "0:                             \n\t"
1010                 "movq (%%esi), %%mm0            \n\t" //FIXME Alignment
1011                 "movq %%mm0, %%mm1              \n\t"
1012                 "psrlq $8, %%mm0                \n\t"
1013                 "punpcklbw %%mm7, %%mm1 \n\t"
1014                 "movq %%mm2, %%mm3              \n\t"
1015                 "punpcklbw %%mm7, %%mm0 \n\t"
1016                 "addw %%bx, %%cx                \n\t" //2*xalpha += (4*lumXInc)&0xFFFF
1017                 "pshufw $0xFF, %%mm1, %%mm1     \n\t"
1018                 "1:                             \n\t"
1019                 "adcl %%edx, %%esi              \n\t" //xx+= (4*lumXInc)>>16 + carry
1020                 "pshufw $0xFF, %%mm0, %%mm0     \n\t"
1021                 "2:                             \n\t"
1022                 "psrlw $9, %%mm3                \n\t"
1023                 "psubw %%mm1, %%mm0             \n\t"
1024                 "pmullw %%mm3, %%mm0            \n\t"
1025                 "paddw %%mm6, %%mm2             \n\t" // 2*alpha += xpos&0xFFFF
1026                 "psllw $7, %%mm1                \n\t"
1027                 "paddw %%mm1, %%mm0             \n\t"
1028
1029                 "movq %%mm0, (%%edi, %%eax)     \n\t"
1030
1031                 "addl $8, %%eax                 \n\t"
1032         // End
1033                 "9:                             \n\t"
1034 //              "int $3\n\t"
1035                 "leal 0b, %0                    \n\t"
1036                 "leal 1b, %1                    \n\t"
1037                 "leal 2b, %2                    \n\t"
1038                 "decl %1                        \n\t"
1039                 "decl %2                        \n\t"
1040                 "subl %0, %1                    \n\t"
1041                 "subl %0, %2                    \n\t"
1042                 "leal 9b, %3                    \n\t"
1043                 "subl %0, %3                    \n\t"
1044                 :"=r" (fragment), "=r" (imm8OfPShufW1), "=r" (imm8OfPShufW2),
1045                 "=r" (fragmentLength)
1046         );
1047
1048         xpos= 0; //lumXInc/2 - 0x8000; // difference between pixel centers
1049
1050         for(i=0; i<dstW/8; i++)
1051         {
1052                 int xx=xpos>>16;
1053
1054                 if((i&3) == 0)
1055                 {
1056                         int a=0;
1057                         int b=((xpos+xInc)>>16) - xx;
1058                         int c=((xpos+xInc*2)>>16) - xx;
1059                         int d=((xpos+xInc*3)>>16) - xx;
1060
1061                         memcpy(funnyCode + fragmentLength*i/4, fragment, fragmentLength);
1062
1063                         funnyCode[fragmentLength*i/4 + imm8OfPShufW1]=
1064                         funnyCode[fragmentLength*i/4 + imm8OfPShufW2]=
1065                                 a | (b<<2) | (c<<4) | (d<<6);
1066
1067                         // if we dont need to read 8 bytes than dont :), reduces the chance of
1068                         // crossing a cache line
1069                         if(d<3) funnyCode[fragmentLength*i/4 + 1]= 0x6E;
1070
1071                         funnyCode[fragmentLength*(i+4)/4]= RET;
1072                 }
1073                 xpos+=xInc;
1074         }
1075 }
1076 #endif // ARCH_X86
1077
1078 //FIXME remove
1079 void SwScale_Init(){
1080 }
1081
1082 static void globalInit(){
1083     // generating tables:
1084     int i;
1085     for(i=0; i<768; i++){
1086         int c= MIN(MAX(i-256, 0), 255);
1087         clip_table[i]=c;
1088         yuvtab_2568[c]= clip_yuvtab_2568[i]=(0x2568*(c-16))+(256<<13);
1089         yuvtab_3343[c]= clip_yuvtab_3343[i]=0x3343*(c-128);
1090         yuvtab_0c92[c]= clip_yuvtab_0c92[i]=-0x0c92*(c-128);
1091         yuvtab_1a1e[c]= clip_yuvtab_1a1e[i]=-0x1a1e*(c-128);
1092         yuvtab_40cf[c]= clip_yuvtab_40cf[i]=0x40cf*(c-128);
1093     }
1094
1095     for(i=0; i<768; i++)
1096     {
1097         int v= clip_table[i];
1098         clip_table16b[i]= le2me_16( v>>3);
1099         clip_table16g[i]= le2me_16((v<<3)&0x07E0);
1100         clip_table16r[i]= le2me_16((v<<8)&0xF800);
1101         clip_table15b[i]= le2me_16( v>>3);
1102         clip_table15g[i]= le2me_16((v<<2)&0x03E0);
1103         clip_table15r[i]= le2me_16((v<<7)&0x7C00);
1104     }
1105
1106 cpuCaps= gCpuCaps;
1107
1108 #ifdef RUNTIME_CPUDETECT
1109 #ifdef CAN_COMPILE_X86_ASM
1110         // ordered per speed fasterst first
1111         if(gCpuCaps.hasMMX2)
1112                 swScale= swScale_MMX2;
1113         else if(gCpuCaps.has3DNow)
1114                 swScale= swScale_3DNow;
1115         else if(gCpuCaps.hasMMX)
1116                 swScale= swScale_MMX;
1117         else
1118                 swScale= swScale_C;
1119
1120 #else
1121         swScale= swScale_C;
1122         cpuCaps.hasMMX2 = cpuCaps.hasMMX = cpuCaps.has3DNow = 0;
1123 #endif
1124 #else //RUNTIME_CPUDETECT
1125 #ifdef HAVE_MMX2
1126         swScale= swScale_MMX2;
1127         cpuCaps.has3DNow = 0;
1128 #elif defined (HAVE_3DNOW)
1129         swScale= swScale_3DNow;
1130         cpuCaps.hasMMX2 = 0;
1131 #elif defined (HAVE_MMX)
1132         swScale= swScale_MMX;
1133         cpuCaps.hasMMX2 = cpuCaps.has3DNow = 0;
1134 #else
1135         swScale= swScale_C;
1136         cpuCaps.hasMMX2 = cpuCaps.hasMMX = cpuCaps.has3DNow = 0;
1137 #endif
1138 #endif //!RUNTIME_CPUDETECT
1139 }
1140
1141 /* Warper functions for yuv2bgr */
1142 static void planarYuvToBgr(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
1143              int srcSliceH, uint8_t* dstParam[], int dstStride[]){
1144         uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
1145
1146         if(c->srcFormat==IMGFMT_YV12)
1147                 yuv2rgb( dst,src[0],src[1],src[2],c->srcW,srcSliceH,dstStride[0],srcStride[0],srcStride[1] );
1148         else /* I420 & IYUV */
1149                 yuv2rgb( dst,src[0],src[2],src[1],c->srcW,srcSliceH,dstStride[0],srcStride[0],srcStride[1] );
1150 }
1151
1152 static void bgr24to32Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
1153              int srcSliceH, uint8_t* dst[], int dstStride[]){
1154         
1155         if(dstStride[0]*3==srcStride[0]*4)
1156                 rgb24to32(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*dstStride[0]>>2);
1157         else
1158         {
1159                 int i;
1160                 uint8_t *srcPtr= src[0];
1161                 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
1162
1163                 for(i=0; i<srcSliceH; i++)
1164                 {
1165                         rgb24to32(srcPtr, dstPtr, c->srcW);
1166                         srcPtr+= srcStride[0];
1167                         dstPtr+= dstStride[0];
1168                 }
1169         }     
1170 }
1171
1172 static void bgr32to24Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
1173              int srcSliceH, uint8_t* dst[], int dstStride[]){
1174         
1175         if(dstStride[0]*4==srcStride[0]*3)
1176                 rgb32to24(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]>>2);
1177         else
1178         {
1179                 int i;
1180                 uint8_t *srcPtr= src[0];
1181                 uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
1182
1183                 for(i=0; i<srcSliceH; i++)
1184                 {
1185                         rgb32to24(srcPtr, dstPtr, c->srcW);
1186                         srcPtr+= srcStride[0];
1187                         dstPtr+= dstStride[0];
1188                 }
1189         }     
1190 }
1191
1192
1193 /* unscaled copy like stuff (assumes nearly identical formats) */
1194 static void simpleCopy(SwsContext *c, uint8_t* srcParam[], int srcStrideParam[], int srcSliceY,
1195              int srcSliceH, uint8_t* dstParam[], int dstStride[]){
1196
1197         int srcStride[3];
1198         uint8_t *src[3];
1199         uint8_t *dst[3];
1200
1201         if(c->srcFormat == IMGFMT_I420){
1202                 src[0]= srcParam[0];
1203                 src[1]= srcParam[2];
1204                 src[2]= srcParam[1];
1205                 srcStride[0]= srcStrideParam[0];
1206                 srcStride[1]= srcStrideParam[2];
1207                 srcStride[2]= srcStrideParam[1];
1208         }
1209         else if(c->srcFormat==IMGFMT_YV12){
1210                 src[0]= srcParam[0];
1211                 src[1]= srcParam[1];
1212                 src[2]= srcParam[2];
1213                 srcStride[0]= srcStrideParam[0];
1214                 srcStride[1]= srcStrideParam[1];
1215                 srcStride[2]= srcStrideParam[2];
1216         }
1217         else if(isPacked(c->srcFormat) || isGray(c->srcFormat)){
1218                 src[0]= srcParam[0];
1219                 src[1]=
1220                 src[2]= NULL;
1221                 srcStride[0]= srcStrideParam[0];
1222                 srcStride[1]=
1223                 srcStride[2]= 0;
1224         }
1225
1226         if(c->dstFormat == IMGFMT_I420){
1227                 dst[0]= dstParam[0];
1228                 dst[1]= dstParam[2];
1229                 dst[2]= dstParam[1];
1230                 
1231         }else{
1232                 dst[0]= dstParam[0];
1233                 dst[1]= dstParam[1];
1234                 dst[2]= dstParam[2];
1235         }
1236
1237         if(isPacked(c->srcFormat))
1238         {
1239                 if(dstStride[0]==srcStride[0])
1240                         memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
1241                 else
1242                 {
1243                         int i;
1244                         uint8_t *srcPtr= src[0];
1245                         uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
1246                         int length=0;
1247
1248                         /* universal length finder */
1249                         while(length+c->srcW <= dstStride[0] 
1250                            && length+c->srcW <= srcStride[0]) length+= c->srcW;
1251                         ASSERT(length!=0);
1252
1253                         for(i=0; i<srcSliceH; i++)
1254                         {
1255                                 memcpy(dstPtr, srcPtr, length);
1256                                 srcPtr+= srcStride[0];
1257                                 dstPtr+= dstStride[0];
1258                         }
1259                 }
1260         }
1261         else 
1262         { /* Planar YUV */
1263                 int plane;
1264                 for(plane=0; plane<3; plane++)
1265                 {
1266                         int length= plane==0 ? c->srcW  : ((c->srcW+1)>>1);
1267                         int y=      plane==0 ? srcSliceY: ((srcSliceY+1)>>1);
1268                         int height= plane==0 ? srcSliceH: ((srcSliceH+1)>>1);
1269
1270                         if(dstStride[plane]==srcStride[plane])
1271                                 memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
1272                         else
1273                         {
1274                                 int i;
1275                                 uint8_t *srcPtr= src[plane];
1276                                 uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
1277                                 for(i=0; i<height; i++)
1278                                 {
1279                                         memcpy(dstPtr, srcPtr, length);
1280                                         srcPtr+= srcStride[plane];
1281                                         dstPtr+= dstStride[plane];
1282                                 }
1283                         }
1284                 }
1285         }
1286 }
1287
1288 SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags,
1289                          SwsFilter *srcFilter, SwsFilter *dstFilter){
1290
1291         SwsContext *c;
1292         int i;
1293         int usesFilter;
1294         SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
1295
1296 #ifdef ARCH_X86
1297         if(gCpuCaps.hasMMX)
1298                 asm volatile("emms\n\t"::: "memory");
1299 #endif
1300
1301         if(swScale==NULL) globalInit();
1302
1303         /* avoid dupplicate Formats, so we dont need to check to much */
1304         if(srcFormat==IMGFMT_IYUV) srcFormat=IMGFMT_I420;
1305         if(srcFormat==IMGFMT_Y8)   srcFormat=IMGFMT_Y800;
1306         if(dstFormat==IMGFMT_Y8)   dstFormat=IMGFMT_Y800;
1307
1308         if(!isSupportedIn(srcFormat)) 
1309         {
1310                 fprintf(stderr, "swScaler: %s is not supported as input format\n", vo_format_name(srcFormat));
1311                 return NULL;
1312         }
1313         if(!isSupportedOut(dstFormat))
1314         {
1315                 fprintf(stderr, "swScaler: %s is not supported as output format\n", vo_format_name(dstFormat));
1316                 return NULL;
1317         }
1318
1319         /* sanity check */
1320         if(srcW<4 || srcH<1 || dstW<8 || dstH<1) //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code
1321         {
1322                 fprintf(stderr, "swScaler: %dx%d -> %dx%d is invalid scaling dimension\n", 
1323                         srcW, srcH, dstW, dstH);
1324                 return NULL;
1325         }
1326
1327         if(!dstFilter) dstFilter= &dummyFilter;
1328         if(!srcFilter) srcFilter= &dummyFilter;
1329
1330         c= memalign(64, sizeof(SwsContext));
1331         memset(c, 0, sizeof(SwsContext));
1332
1333         c->srcW= srcW;
1334         c->srcH= srcH;
1335         c->dstW= dstW;
1336         c->dstH= dstH;
1337         c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW;
1338         c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH;
1339         c->flags= flags;
1340         c->dstFormat= dstFormat;
1341         c->srcFormat= srcFormat;
1342
1343         usesFilter=0;
1344         if(dstFilter->lumV!=NULL && dstFilter->lumV->length>1) usesFilter=1;
1345         if(dstFilter->lumH!=NULL && dstFilter->lumH->length>1) usesFilter=1;
1346         if(dstFilter->chrV!=NULL && dstFilter->chrV->length>1) usesFilter=1;
1347         if(dstFilter->chrH!=NULL && dstFilter->chrH->length>1) usesFilter=1;
1348         if(srcFilter->lumV!=NULL && srcFilter->lumV->length>1) usesFilter=1;
1349         if(srcFilter->lumH!=NULL && srcFilter->lumH->length>1) usesFilter=1;
1350         if(srcFilter->chrV!=NULL && srcFilter->chrV->length>1) usesFilter=1;
1351         if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesFilter=1;
1352         
1353         /* unscaled special Cases */
1354         if(srcW==dstW && srcH==dstH && !usesFilter)
1355         {
1356                 /* yuv2bgr */
1357                 if(isPlanarYUV(srcFormat) && isBGR(dstFormat))
1358                 {
1359                         // FIXME multiple yuv2rgb converters wont work that way cuz that thing is full of globals&statics
1360                         yuv2rgb_init( dstFormat&0xFF /* =bpp */, MODE_RGB);
1361                         c->swScale= planarYuvToBgr;
1362
1363                         if(flags&SWS_PRINT_INFO)
1364                                 printf("SwScaler: using unscaled %s -> %s special converter\n", 
1365                                         vo_format_name(srcFormat), vo_format_name(dstFormat));
1366                         return c;
1367                 }
1368
1369                 /* simple copy */
1370                 if(srcFormat == dstFormat || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)))
1371                 {
1372                         c->swScale= simpleCopy;
1373
1374                         if(flags&SWS_PRINT_INFO)
1375                                 printf("SwScaler: using unscaled %s -> %s special converter\n", 
1376                                         vo_format_name(srcFormat), vo_format_name(dstFormat));
1377                         return c;
1378                 }
1379                 
1380                 /* bgr32to24 & rgb32to24*/
1381                 if((srcFormat==IMGFMT_BGR32 && dstFormat==IMGFMT_BGR24)
1382                  ||(srcFormat==IMGFMT_RGB32 && dstFormat==IMGFMT_RGB24))
1383                 {
1384                         c->swScale= bgr32to24Wrapper;
1385
1386                         if(flags&SWS_PRINT_INFO)
1387                                 printf("SwScaler: using unscaled %s -> %s special converter\n", 
1388                                         vo_format_name(srcFormat), vo_format_name(dstFormat));
1389                         return c;
1390                 }
1391                 
1392                 /* bgr24to32 & rgb24to32*/
1393                 if((srcFormat==IMGFMT_BGR24 && dstFormat==IMGFMT_BGR32)
1394                  ||(srcFormat==IMGFMT_RGB24 && dstFormat==IMGFMT_RGB32))
1395                 {
1396                         c->swScale= bgr24to32Wrapper;
1397
1398                         if(flags&SWS_PRINT_INFO)
1399                                 printf("SwScaler: using unscaled %s -> %s special converter\n", 
1400                                         vo_format_name(srcFormat), vo_format_name(dstFormat));
1401                         return c;
1402                 }
1403         }
1404
1405         if(cpuCaps.hasMMX2)
1406         {
1407                 c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0;
1408                 if(!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR))
1409                 {
1410                         if(flags&SWS_PRINT_INFO)
1411                                 fprintf(stderr, "SwScaler: output Width is not a multiple of 32 -> no MMX2 scaler\n");
1412                 }
1413         }
1414         else
1415                 c->canMMX2BeUsed=0;
1416
1417
1418         /* dont use full vertical UV input/internaly if the source doesnt even have it */
1419         if(isHalfChrV(srcFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_V);
1420         /* dont use full horizontal UV input if the source doesnt even have it */
1421         if(isHalfChrH(srcFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_H_INP);
1422         /* dont use full horizontal UV internally if the destination doesnt even have it */
1423         if(isHalfChrH(dstFormat)) c->flags= flags= flags&(~SWS_FULL_CHR_H_INT);
1424
1425         if(flags&SWS_FULL_CHR_H_INP)    c->chrSrcW= srcW;
1426         else                            c->chrSrcW= (srcW+1)>>1;
1427
1428         if(flags&SWS_FULL_CHR_H_INT)    c->chrDstW= dstW;
1429         else                            c->chrDstW= (dstW+1)>>1;
1430
1431         if(flags&SWS_FULL_CHR_V)        c->chrSrcH= srcH;
1432         else                            c->chrSrcH= (srcH+1)>>1;
1433
1434         if(isHalfChrV(dstFormat))       c->chrDstH= (dstH+1)>>1;
1435         else                            c->chrDstH= dstH;
1436
1437         c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW;
1438         c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH;
1439
1440
1441         // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst
1442         // but only for the FAST_BILINEAR mode otherwise do correct scaling
1443         // n-2 is the last chrominance sample available
1444         // this is not perfect, but noone shuld notice the difference, the more correct variant
1445         // would be like the vertical one, but that would require some special code for the
1446         // first and last pixel
1447         if(flags&SWS_FAST_BILINEAR)
1448         {
1449                 if(c->canMMX2BeUsed)
1450                 {
1451                         c->lumXInc+= 20;
1452                         c->chrXInc+= 20;
1453                 }
1454                 //we dont use the x86asm scaler if mmx is available
1455                 else if(cpuCaps.hasMMX)
1456                 {
1457                         c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20;
1458                         c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20;
1459                 }
1460         }
1461
1462         /* precalculate horizontal scaler filter coefficients */
1463         {
1464                 const int filterAlign= cpuCaps.hasMMX ? 4 : 1;
1465
1466                 initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc,
1467                                  srcW      ,       dstW, filterAlign, 1<<14, flags,
1468                                  srcFilter->lumH, dstFilter->lumH);
1469                 initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc,
1470                                 (srcW+1)>>1, c->chrDstW, filterAlign, 1<<14, flags,
1471                                  srcFilter->chrH, dstFilter->chrH);
1472
1473 #ifdef ARCH_X86
1474 // cant downscale !!!
1475                 if(c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR))
1476                 {
1477                         initMMX2HScaler(      dstW, c->lumXInc, c->funnyYCode);
1478                         initMMX2HScaler(c->chrDstW, c->chrXInc, c->funnyUVCode);
1479                 }
1480 #endif
1481         } // Init Horizontal stuff
1482
1483
1484
1485         /* precalculate vertical scaler filter coefficients */
1486         initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc,
1487                         srcH      ,        dstH, 1, (1<<12)-4, flags,
1488                         srcFilter->lumV, dstFilter->lumV);
1489         initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc,
1490                         (srcH+1)>>1, c->chrDstH, 1, (1<<12)-4, flags,
1491                          srcFilter->chrV, dstFilter->chrV);
1492
1493         // Calculate Buffer Sizes so that they wont run out while handling these damn slices
1494         c->vLumBufSize= c->vLumFilterSize;
1495         c->vChrBufSize= c->vChrFilterSize;
1496         for(i=0; i<dstH; i++)
1497         {
1498                 int chrI= i*c->chrDstH / dstH;
1499                 int nextSlice= MAX(c->vLumFilterPos[i   ] + c->vLumFilterSize - 1,
1500                                  ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<1));
1501                 nextSlice&= ~1; // Slices start at even boundaries
1502                 if(c->vLumFilterPos[i   ] + c->vLumBufSize < nextSlice)
1503                         c->vLumBufSize= nextSlice - c->vLumFilterPos[i   ];
1504                 if(c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>1))
1505                         c->vChrBufSize= (nextSlice>>1) - c->vChrFilterPos[chrI];
1506         }
1507
1508         // allocate pixbufs (we use dynamic allocation because otherwise we would need to
1509         c->lumPixBuf= (int16_t**)memalign(4, c->vLumBufSize*2*sizeof(int16_t*));
1510         c->chrPixBuf= (int16_t**)memalign(4, c->vChrBufSize*2*sizeof(int16_t*));
1511         //Note we need at least one pixel more at the end because of the mmx code (just in case someone wanna replace the 4000/8000)
1512         for(i=0; i<c->vLumBufSize; i++)
1513                 c->lumPixBuf[i]= c->lumPixBuf[i+c->vLumBufSize]= (uint16_t*)memalign(8, 4000);
1514         for(i=0; i<c->vChrBufSize; i++)
1515                 c->chrPixBuf[i]= c->chrPixBuf[i+c->vChrBufSize]= (uint16_t*)memalign(8, 8000);
1516
1517         //try to avoid drawing green stuff between the right end and the stride end
1518         for(i=0; i<c->vLumBufSize; i++) memset(c->lumPixBuf[i], 0, 4000);
1519         for(i=0; i<c->vChrBufSize; i++) memset(c->chrPixBuf[i], 64, 8000);
1520
1521         ASSERT(c->chrDstH <= dstH)
1522
1523         // pack filter data for mmx code
1524         if(cpuCaps.hasMMX)
1525         {
1526                 c->lumMmxFilter= (int16_t*)memalign(8, c->vLumFilterSize*      dstH*4*sizeof(int16_t));
1527                 c->chrMmxFilter= (int16_t*)memalign(8, c->vChrFilterSize*c->chrDstH*4*sizeof(int16_t));
1528                 for(i=0; i<c->vLumFilterSize*dstH; i++)
1529                         c->lumMmxFilter[4*i]=c->lumMmxFilter[4*i+1]=c->lumMmxFilter[4*i+2]=c->lumMmxFilter[4*i+3]=
1530                                 c->vLumFilter[i];
1531                 for(i=0; i<c->vChrFilterSize*c->chrDstH; i++)
1532                         c->chrMmxFilter[4*i]=c->chrMmxFilter[4*i+1]=c->chrMmxFilter[4*i+2]=c->chrMmxFilter[4*i+3]=
1533                                 c->vChrFilter[i];
1534         }
1535
1536         if(flags&SWS_PRINT_INFO)
1537         {
1538 #ifdef DITHER1XBPP
1539                 char *dither= " dithered";
1540 #else
1541                 char *dither= "";
1542 #endif
1543                 if(flags&SWS_FAST_BILINEAR)
1544                         fprintf(stderr, "\nSwScaler: FAST_BILINEAR scaler, ");
1545                 else if(flags&SWS_BILINEAR)
1546                         fprintf(stderr, "\nSwScaler: BILINEAR scaler, ");
1547                 else if(flags&SWS_BICUBIC)
1548                         fprintf(stderr, "\nSwScaler: BICUBIC scaler, ");
1549                 else if(flags&SWS_X)
1550                         fprintf(stderr, "\nSwScaler: Experimental scaler, ");
1551                 else if(flags&SWS_POINT)
1552                         fprintf(stderr, "\nSwScaler: Nearest Neighbor / POINT scaler, ");
1553                 else if(flags&SWS_AREA)
1554                         fprintf(stderr, "\nSwScaler: Area Averageing scaler, ");
1555                 else
1556                         fprintf(stderr, "\nSwScaler: ehh flags invalid?! ");
1557
1558                 if(dstFormat==IMGFMT_BGR15 || dstFormat==IMGFMT_BGR16)
1559                         fprintf(stderr, "from %s to%s %s ", 
1560                                 vo_format_name(srcFormat), dither, vo_format_name(dstFormat));
1561                 else
1562                         fprintf(stderr, "from %s to %s ", 
1563                                 vo_format_name(srcFormat), vo_format_name(dstFormat));
1564
1565                 if(cpuCaps.hasMMX2)
1566                         fprintf(stderr, "using MMX2\n");
1567                 else if(cpuCaps.has3DNow)
1568                         fprintf(stderr, "using 3DNOW\n");
1569                 else if(cpuCaps.hasMMX)
1570                         fprintf(stderr, "using MMX\n");
1571                 else
1572                         fprintf(stderr, "using C\n");
1573         }
1574
1575         if((flags & SWS_PRINT_INFO) && verbose)
1576         {
1577                 if(cpuCaps.hasMMX)
1578                 {
1579                         if(c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR))
1580                                 printf("SwScaler: using FAST_BILINEAR MMX2 scaler for horizontal scaling\n");
1581                         else
1582                         {
1583                                 if(c->hLumFilterSize==4)
1584                                         printf("SwScaler: using 4-tap MMX scaler for horizontal luminance scaling\n");
1585                                 else if(c->hLumFilterSize==8)
1586                                         printf("SwScaler: using 8-tap MMX scaler for horizontal luminance scaling\n");
1587                                 else
1588                                         printf("SwScaler: using n-tap MMX scaler for horizontal luminance scaling\n");
1589
1590                                 if(c->hChrFilterSize==4)
1591                                         printf("SwScaler: using 4-tap MMX scaler for horizontal chrominance scaling\n");
1592                                 else if(c->hChrFilterSize==8)
1593                                         printf("SwScaler: using 8-tap MMX scaler for horizontal chrominance scaling\n");
1594                                 else
1595                                         printf("SwScaler: using n-tap MMX scaler for horizontal chrominance scaling\n");
1596                         }
1597                 }
1598                 else
1599                 {
1600 #ifdef ARCH_X86
1601                         printf("SwScaler: using X86-Asm scaler for horizontal scaling\n");
1602 #else
1603                         if(flags & SWS_FAST_BILINEAR)
1604                                 printf("SwScaler: using FAST_BILINEAR C scaler for horizontal scaling\n");
1605                         else
1606                                 printf("SwScaler: using C scaler for horizontal scaling\n");
1607 #endif
1608                 }
1609                 if(isPlanarYUV(dstFormat))
1610                 {
1611                         if(c->vLumFilterSize==1)
1612                                 printf("SwScaler: using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n", cpuCaps.hasMMX ? "MMX" : "C");
1613                         else
1614                                 printf("SwScaler: using n-tap %s scaler for vertical scaling (YV12 like)\n", cpuCaps.hasMMX ? "MMX" : "C");
1615                 }
1616                 else
1617                 {
1618                         if(c->vLumFilterSize==1 && c->vChrFilterSize==2)
1619                                 printf("SwScaler: using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n"
1620                                        "SwScaler:       2-tap scaler for vertical chrominance scaling (BGR)\n",cpuCaps.hasMMX ? "MMX" : "C");
1621                         else if(c->vLumFilterSize==2 && c->vChrFilterSize==2)
1622                                 printf("SwScaler: using 2-tap linear %s scaler for vertical scaling (BGR)\n", cpuCaps.hasMMX ? "MMX" : "C");
1623                         else
1624                                 printf("SwScaler: using n-tap %s scaler for vertical scaling (BGR)\n", cpuCaps.hasMMX ? "MMX" : "C");
1625                 }
1626
1627                 if(dstFormat==IMGFMT_BGR24)
1628                         printf("SwScaler: using %s YV12->BGR24 Converter\n",
1629                                 cpuCaps.hasMMX2 ? "MMX2" : (cpuCaps.hasMMX ? "MMX" : "C"));
1630                 else if(dstFormat==IMGFMT_BGR32)
1631                         printf("SwScaler: using %s YV12->BGR32 Converter\n", cpuCaps.hasMMX ? "MMX" : "C");
1632                 else if(dstFormat==IMGFMT_BGR16)
1633                         printf("SwScaler: using %s YV12->BGR16 Converter\n", cpuCaps.hasMMX ? "MMX" : "C");
1634                 else if(dstFormat==IMGFMT_BGR15)
1635                         printf("SwScaler: using %s YV12->BGR15 Converter\n", cpuCaps.hasMMX ? "MMX" : "C");
1636
1637                 printf("SwScaler: %dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
1638         }
1639         if((flags & SWS_PRINT_INFO) && verbose>1)
1640         {
1641                 printf("SwScaler:Lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1642                         c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
1643                 printf("SwScaler:Chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1644                         c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc);
1645         }
1646
1647         c->swScale= swScale;
1648         return c;
1649 }
1650
1651 /**
1652  * returns a normalized gaussian curve used to filter stuff
1653  * quality=3 is high quality, lowwer is lowwer quality
1654  */
1655
1656 SwsVector *getGaussianVec(double variance, double quality){
1657         const int length= (int)(variance*quality + 0.5) | 1;
1658         int i;
1659         double *coeff= memalign(sizeof(double), length*sizeof(double));
1660         double middle= (length-1)*0.5;
1661         SwsVector *vec= malloc(sizeof(SwsVector));
1662
1663         vec->coeff= coeff;
1664         vec->length= length;
1665
1666         for(i=0; i<length; i++)
1667         {
1668                 double dist= i-middle;
1669                 coeff[i]= exp( -dist*dist/(2*variance*variance) ) / sqrt(2*variance*PI);
1670         }
1671
1672         normalizeVec(vec, 1.0);
1673
1674         return vec;
1675 }
1676
1677 SwsVector *getConstVec(double c, int length){
1678         int i;
1679         double *coeff= memalign(sizeof(double), length*sizeof(double));
1680         SwsVector *vec= malloc(sizeof(SwsVector));
1681
1682         vec->coeff= coeff;
1683         vec->length= length;
1684
1685         for(i=0; i<length; i++)
1686                 coeff[i]= c;
1687
1688         return vec;
1689 }
1690
1691
1692 SwsVector *getIdentityVec(void){
1693         double *coeff= memalign(sizeof(double), sizeof(double));
1694         SwsVector *vec= malloc(sizeof(SwsVector));
1695         coeff[0]= 1.0;
1696
1697         vec->coeff= coeff;
1698         vec->length= 1;
1699
1700         return vec;
1701 }
1702
1703 void normalizeVec(SwsVector *a, double height){
1704         int i;
1705         double sum=0;
1706         double inv;
1707
1708         for(i=0; i<a->length; i++)
1709                 sum+= a->coeff[i];
1710
1711         inv= height/sum;
1712
1713         for(i=0; i<a->length; i++)
1714                 a->coeff[i]*= height;
1715 }
1716
1717 void scaleVec(SwsVector *a, double scalar){
1718         int i;
1719
1720         for(i=0; i<a->length; i++)
1721                 a->coeff[i]*= scalar;
1722 }
1723
1724 static SwsVector *getConvVec(SwsVector *a, SwsVector *b){
1725         int length= a->length + b->length - 1;
1726         double *coeff= memalign(sizeof(double), length*sizeof(double));
1727         int i, j;
1728         SwsVector *vec= malloc(sizeof(SwsVector));
1729
1730         vec->coeff= coeff;
1731         vec->length= length;
1732
1733         for(i=0; i<length; i++) coeff[i]= 0.0;
1734
1735         for(i=0; i<a->length; i++)
1736         {
1737                 for(j=0; j<b->length; j++)
1738                 {
1739                         coeff[i+j]+= a->coeff[i]*b->coeff[j];
1740                 }
1741         }
1742
1743         return vec;
1744 }
1745
1746 static SwsVector *sumVec(SwsVector *a, SwsVector *b){
1747         int length= MAX(a->length, b->length);
1748         double *coeff= memalign(sizeof(double), length*sizeof(double));
1749         int i;
1750         SwsVector *vec= malloc(sizeof(SwsVector));
1751
1752         vec->coeff= coeff;
1753         vec->length= length;
1754
1755         for(i=0; i<length; i++) coeff[i]= 0.0;
1756
1757         for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
1758         for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]+= b->coeff[i];
1759
1760         return vec;
1761 }
1762
1763 static SwsVector *diffVec(SwsVector *a, SwsVector *b){
1764         int length= MAX(a->length, b->length);
1765         double *coeff= memalign(sizeof(double), length*sizeof(double));
1766         int i;
1767         SwsVector *vec= malloc(sizeof(SwsVector));
1768
1769         vec->coeff= coeff;
1770         vec->length= length;
1771
1772         for(i=0; i<length; i++) coeff[i]= 0.0;
1773
1774         for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i];
1775         for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]-= b->coeff[i];
1776
1777         return vec;
1778 }
1779
1780 /* shift left / or right if "shift" is negative */
1781 static SwsVector *getShiftedVec(SwsVector *a, int shift){
1782         int length= a->length + ABS(shift)*2;
1783         double *coeff= memalign(sizeof(double), length*sizeof(double));
1784         int i;
1785         SwsVector *vec= malloc(sizeof(SwsVector));
1786
1787         vec->coeff= coeff;
1788         vec->length= length;
1789
1790         for(i=0; i<length; i++) coeff[i]= 0.0;
1791
1792         for(i=0; i<a->length; i++)
1793         {
1794                 coeff[i + (length-1)/2 - (a->length-1)/2 - shift]= a->coeff[i];
1795         }
1796
1797         return vec;
1798 }
1799
1800 void shiftVec(SwsVector *a, int shift){
1801         SwsVector *shifted= getShiftedVec(a, shift);
1802         free(a->coeff);
1803         a->coeff= shifted->coeff;
1804         a->length= shifted->length;
1805         free(shifted);
1806 }
1807
1808 void addVec(SwsVector *a, SwsVector *b){
1809         SwsVector *sum= sumVec(a, b);
1810         free(a->coeff);
1811         a->coeff= sum->coeff;
1812         a->length= sum->length;
1813         free(sum);
1814 }
1815
1816 void subVec(SwsVector *a, SwsVector *b){
1817         SwsVector *diff= diffVec(a, b);
1818         free(a->coeff);
1819         a->coeff= diff->coeff;
1820         a->length= diff->length;
1821         free(diff);
1822 }
1823
1824 void convVec(SwsVector *a, SwsVector *b){
1825         SwsVector *conv= getConvVec(a, b);
1826         free(a->coeff);
1827         a->coeff= conv->coeff;
1828         a->length= conv->length;
1829         free(conv);
1830 }
1831
1832 SwsVector *cloneVec(SwsVector *a){
1833         double *coeff= memalign(sizeof(double), a->length*sizeof(double));
1834         int i;
1835         SwsVector *vec= malloc(sizeof(SwsVector));
1836
1837         vec->coeff= coeff;
1838         vec->length= a->length;
1839
1840         for(i=0; i<a->length; i++) coeff[i]= a->coeff[i];
1841
1842         return vec;
1843 }
1844
1845 void printVec(SwsVector *a){
1846         int i;
1847         double max=0;
1848         double min=0;
1849         double range;
1850
1851         for(i=0; i<a->length; i++)
1852                 if(a->coeff[i]>max) max= a->coeff[i];
1853
1854         for(i=0; i<a->length; i++)
1855                 if(a->coeff[i]<min) min= a->coeff[i];
1856
1857         range= max - min;
1858
1859         for(i=0; i<a->length; i++)
1860         {
1861                 int x= (int)((a->coeff[i]-min)*60.0/range +0.5);
1862                 printf("%1.3f ", a->coeff[i]);
1863                 for(;x>0; x--) printf(" ");
1864                 printf("|\n");
1865         }
1866 }
1867
1868 void freeVec(SwsVector *a){
1869         if(!a) return;
1870         if(a->coeff) free(a->coeff);
1871         a->coeff=NULL;
1872         a->length=0;
1873         free(a);
1874 }
1875
1876 void freeSwsContext(SwsContext *c){
1877         int i;
1878
1879         if(!c) return;
1880
1881         if(c->lumPixBuf)
1882         {
1883                 for(i=0; i<c->vLumBufSize; i++)
1884                 {
1885                         if(c->lumPixBuf[i]) free(c->lumPixBuf[i]);
1886                         c->lumPixBuf[i]=NULL;
1887                 }
1888                 free(c->lumPixBuf);
1889                 c->lumPixBuf=NULL;
1890         }
1891
1892         if(c->chrPixBuf)
1893         {
1894                 for(i=0; i<c->vChrBufSize; i++)
1895                 {
1896                         if(c->chrPixBuf[i]) free(c->chrPixBuf[i]);
1897                         c->chrPixBuf[i]=NULL;
1898                 }
1899                 free(c->chrPixBuf);
1900                 c->chrPixBuf=NULL;
1901         }
1902
1903         if(c->vLumFilter) free(c->vLumFilter);
1904         c->vLumFilter = NULL;
1905         if(c->vChrFilter) free(c->vChrFilter);
1906         c->vChrFilter = NULL;
1907         if(c->hLumFilter) free(c->hLumFilter);
1908         c->hLumFilter = NULL;
1909         if(c->hChrFilter) free(c->hChrFilter);
1910         c->hChrFilter = NULL;
1911
1912         if(c->vLumFilterPos) free(c->vLumFilterPos);
1913         c->vLumFilterPos = NULL;
1914         if(c->vChrFilterPos) free(c->vChrFilterPos);
1915         c->vChrFilterPos = NULL;
1916         if(c->hLumFilterPos) free(c->hLumFilterPos);
1917         c->hLumFilterPos = NULL;
1918         if(c->hChrFilterPos) free(c->hChrFilterPos);
1919         c->hChrFilterPos = NULL;
1920
1921         if(c->lumMmxFilter) free(c->lumMmxFilter);
1922         c->lumMmxFilter = NULL;
1923         if(c->chrMmxFilter) free(c->chrMmxFilter);
1924         c->chrMmxFilter = NULL;
1925
1926         free(c);
1927 }
1928
1929