Commit | Line | Data |
---|---|---|
fe8054c0 | 1 | /* |
d026b45e DB |
2 | * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> |
3 | * | |
4 | * This file is part of FFmpeg. | |
5 | * | |
6 | * FFmpeg is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * FFmpeg is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with FFmpeg; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | * | |
807e0c66 LA |
20 | * the C code (not assembly, mmx, ...) of this file can be used |
21 | * under the LGPL license too | |
d026b45e | 22 | */ |
783e9cc9 | 23 | |
28bf81c9 | 24 | /* |
e28630fc | 25 | supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8/Y800, YVU9/IF09, PAL8 |
caeaabe7 | 26 | supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09 |
e09d12f4 | 27 | {BGR,RGB}{1,4,8,15,16} support dithering |
6a4970ab | 28 | |
e09d12f4 MN |
29 | unscaled special converters (YV12=I420=IYUV, Y800=Y8) |
30 | YV12 -> {BGR,RGB}{1,4,8,15,16,24,32} | |
31 | x -> x | |
32 | YUV9 -> YV12 | |
33 | YUV9/YV12 -> Y800 | |
34 | Y800 -> YUV9/YV12 | |
b935781b MN |
35 | BGR24 -> BGR32 & RGB24 -> RGB32 |
36 | BGR32 -> BGR24 & RGB32 -> RGB24 | |
4bb3fa5e | 37 | BGR15 -> BGR16 |
b935781b MN |
38 | */ |
39 | ||
6a4970ab | 40 | /* |
e09d12f4 MN |
41 | tested special converters (most are tested actually but i didnt write it down ...) |
42 | YV12 -> BGR16 | |
b935781b | 43 | YV12 -> YV12 |
4bb3fa5e | 44 | BGR15 -> BGR16 |
1e1c4fe9 | 45 | BGR16 -> BGR16 |
e09d12f4 | 46 | YVU9 -> YV12 |
b935781b MN |
47 | |
48 | untested special converters | |
1e1c4fe9 MN |
49 | YV12/I420 -> BGR15/BGR24/BGR32 (its the yuv2rgb stuff, so it should be ok) |
50 | YV12/I420 -> YV12/I420 | |
51 | YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format | |
b935781b MN |
52 | BGR24 -> BGR32 & RGB24 -> RGB32 |
53 | BGR32 -> BGR24 & RGB32 -> RGB24 | |
ec22603f | 54 | BGR24 -> YV12 |
28bf81c9 MN |
55 | */ |
56 | ||
d3f41512 | 57 | #include <inttypes.h> |
dda87e9f | 58 | #include <string.h> |
077ea8a7 | 59 | #include <math.h> |
c1b0bfb4 | 60 | #include <stdio.h> |
171d7d78 | 61 | #include <unistd.h> |
b2d374c9 | 62 | #include "config.h" |
81b7c056 | 63 | #include <assert.h> |
38d5c282 AJ |
64 | #ifdef HAVE_SYS_MMAN_H |
65 | #include <sys/mman.h> | |
113ef149 RD |
66 | #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) |
67 | #define MAP_ANONYMOUS MAP_ANON | |
68 | #endif | |
38d5c282 | 69 | #endif |
d604bab9 | 70 | #include "swscale.h" |
5427e242 | 71 | #include "swscale_internal.h" |
94c4def2 | 72 | #include "x86_cpu.h" |
b2d374c9 | 73 | #include "bswap.h" |
37079906 | 74 | #include "rgb2rgb.h" |
94c4def2 | 75 | #ifdef USE_FASTMEMCPY |
b2d374c9 | 76 | #include "libvo/fastmemcpy.h" |
94c4def2 | 77 | #endif |
0d9f3d85 | 78 | |
541c4eb9 | 79 | #undef MOVNTQ |
7d7f78b5 | 80 | #undef PAVGB |
d3f41512 | 81 | |
783e9cc9 | 82 | //#undef HAVE_MMX2 |
7f56a527 | 83 | //#define HAVE_3DNOW |
d3f41512 | 84 | //#undef HAVE_MMX |
783e9cc9 | 85 | //#undef ARCH_X86 |
2ba1bff0 | 86 | //#define WORDS_BIGENDIAN |
d604bab9 | 87 | #define DITHER1XBPP |
d3f41512 | 88 | |
ac6a2e45 MN |
89 | #define FAST_BGR2YV12 // use 7 bit coeffs instead of 15bit |
90 | ||
1e621b18 | 91 | #define RET 0xC3 //near return opcode for X86 |
c1b0bfb4 | 92 | |
28bf81c9 | 93 | #ifdef MP_DEBUG |
81b7c056 | 94 | #define ASSERT(x) assert(x); |
28bf81c9 | 95 | #else |
c1b0bfb4 | 96 | #define ASSERT(x) ; |
28bf81c9 MN |
97 | #endif |
98 | ||
99 | #ifdef M_PI | |
100 | #define PI M_PI | |
101 | #else | |
102 | #define PI 3.14159265358979323846 | |
103 | #endif | |
c1b0bfb4 | 104 | |
e9e12f0e LA |
105 | #define isSupportedIn(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422\ |
106 | || (x)==PIX_FMT_RGB32|| (x)==PIX_FMT_BGR24|| (x)==PIX_FMT_BGR565|| (x)==PIX_FMT_BGR555\ | |
a43fb6b3 | 107 | || (x)==PIX_FMT_BGR32|| (x)==PIX_FMT_RGB24|| (x)==PIX_FMT_RGB565|| (x)==PIX_FMT_RGB555\ |
e9e12f0e | 108 | || (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P\ |
4884b9e5 | 109 | || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\ |
e28630fc | 110 | || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P\ |
18064f5c MN |
111 | || (x)==PIX_FMT_PAL8 || (x)==PIX_FMT_BGR8 || (x)==PIX_FMT_RGB8\ |
112 | || (x)==PIX_FMT_BGR4_BYTE || (x)==PIX_FMT_RGB4_BYTE) | |
e9e12f0e LA |
113 | #define isSupportedOut(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422\ |
114 | || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P\ | |
cf7d1c1a | 115 | || isRGB(x) || isBGR(x)\ |
e9e12f0e | 116 | || (x)==PIX_FMT_NV12 || (x)==PIX_FMT_NV21\ |
4884b9e5 | 117 | || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\ |
e9e12f0e | 118 | || (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P) |
6cbac7ed KB |
119 | #define isPacked(x) ((x)==PIX_FMT_PAL8 || (x)==PIX_FMT_YUYV422 ||\ |
120 | (x)==PIX_FMT_UYVY422 || isRGB(x) || isBGR(x)) | |
6ff0ad6b MN |
121 | |
122 | #define RGB2YUV_SHIFT 16 | |
1e621b18 MN |
123 | #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5)) |
124 | #define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5)) | |
125 | #define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5)) | |
126 | #define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5)) | |
127 | #define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5)) | |
128 | #define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5)) | |
129 | #define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5)) | |
130 | #define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5)) | |
131 | #define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5)) | |
6c7506de | 132 | |
0481412a MN |
133 | extern const int32_t Inverse_Table_6_9[8][4]; |
134 | ||
783e9cc9 MN |
135 | /* |
136 | NOTES | |
d604bab9 | 137 | Special versions: fast Y 1:1 scaling (no interpolation in y direction) |
31190492 | 138 | |
783e9cc9 | 139 | TODO |
d604bab9 | 140 | more intelligent missalignment avoidance for the horizontal scaler |
c1b0bfb4 MN |
141 | write special vertical cubic upscale version |
142 | Optimize C code (yv12 / minmax) | |
ff7ba856 | 143 | add support for packed pixel yuv input & output |
6ff0ad6b MN |
144 | add support for Y8 output |
145 | optimize bgr24 & bgr32 | |
ff7ba856 | 146 | add BGR4 output support |
1e621b18 | 147 | write special BGR->BGR scaler |
783e9cc9 | 148 | */ |
31190492 | 149 | |
9bde778e | 150 | #if defined(ARCH_X86) && defined (CONFIG_GPL) |
db7a2e0d MC |
151 | static uint64_t attribute_used __attribute__((aligned(8))) bF8= 0xF8F8F8F8F8F8F8F8LL; |
152 | static uint64_t attribute_used __attribute__((aligned(8))) bFC= 0xFCFCFCFCFCFCFCFCLL; | |
d604bab9 | 153 | static uint64_t __attribute__((aligned(8))) w10= 0x0010001000100010LL; |
db7a2e0d MC |
154 | static uint64_t attribute_used __attribute__((aligned(8))) w02= 0x0002000200020002LL; |
155 | static uint64_t attribute_used __attribute__((aligned(8))) bm00001111=0x00000000FFFFFFFFLL; | |
156 | static uint64_t attribute_used __attribute__((aligned(8))) bm00000111=0x0000000000FFFFFFLL; | |
157 | static uint64_t attribute_used __attribute__((aligned(8))) bm11111000=0xFFFFFFFFFF000000LL; | |
158 | static uint64_t attribute_used __attribute__((aligned(8))) bm01010101=0x00FF00FF00FF00FFLL; | |
d604bab9 | 159 | |
db7a2e0d MC |
160 | static volatile uint64_t attribute_used __attribute__((aligned(8))) b5Dither; |
161 | static volatile uint64_t attribute_used __attribute__((aligned(8))) g5Dither; | |
162 | static volatile uint64_t attribute_used __attribute__((aligned(8))) g6Dither; | |
163 | static volatile uint64_t attribute_used __attribute__((aligned(8))) r5Dither; | |
d8fa3c54 MN |
164 | |
165 | static uint64_t __attribute__((aligned(8))) dither4[2]={ | |
166 | 0x0103010301030103LL, | |
167 | 0x0200020002000200LL,}; | |
168 | ||
169 | static uint64_t __attribute__((aligned(8))) dither8[2]={ | |
170 | 0x0602060206020602LL, | |
171 | 0x0004000400040004LL,}; | |
d604bab9 MN |
172 | |
173 | static uint64_t __attribute__((aligned(8))) b16Mask= 0x001F001F001F001FLL; | |
db7a2e0d MC |
174 | static uint64_t attribute_used __attribute__((aligned(8))) g16Mask= 0x07E007E007E007E0LL; |
175 | static uint64_t attribute_used __attribute__((aligned(8))) r16Mask= 0xF800F800F800F800LL; | |
d604bab9 | 176 | static uint64_t __attribute__((aligned(8))) b15Mask= 0x001F001F001F001FLL; |
db7a2e0d MC |
177 | static uint64_t attribute_used __attribute__((aligned(8))) g15Mask= 0x03E003E003E003E0LL; |
178 | static uint64_t attribute_used __attribute__((aligned(8))) r15Mask= 0x7C007C007C007C00LL; | |
d604bab9 | 179 | |
db7a2e0d MC |
180 | static uint64_t attribute_used __attribute__((aligned(8))) M24A= 0x00FF0000FF0000FFLL; |
181 | static uint64_t attribute_used __attribute__((aligned(8))) M24B= 0xFF0000FF0000FF00LL; | |
182 | static uint64_t attribute_used __attribute__((aligned(8))) M24C= 0x0000FF0000FF0000LL; | |
99d2cb72 | 183 | |
ac6a2e45 | 184 | #ifdef FAST_BGR2YV12 |
db7a2e0d MC |
185 | static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000000210041000DULL; |
186 | static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000FFEEFFDC0038ULL; | |
187 | static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00000038FFD2FFF8ULL; | |
ac6a2e45 | 188 | #else |
db7a2e0d MC |
189 | static const uint64_t bgr2YCoeff attribute_used __attribute__((aligned(8))) = 0x000020E540830C8BULL; |
190 | static const uint64_t bgr2UCoeff attribute_used __attribute__((aligned(8))) = 0x0000ED0FDAC23831ULL; | |
191 | static const uint64_t bgr2VCoeff attribute_used __attribute__((aligned(8))) = 0x00003831D0E6F6EAULL; | |
69796008 | 192 | #endif /* FAST_BGR2YV12 */ |
db7a2e0d MC |
193 | static const uint64_t bgr2YOffset attribute_used __attribute__((aligned(8))) = 0x1010101010101010ULL; |
194 | static const uint64_t bgr2UVOffset attribute_used __attribute__((aligned(8)))= 0x8080808080808080ULL; | |
195 | static const uint64_t w1111 attribute_used __attribute__((aligned(8))) = 0x0001000100010001ULL; | |
3d6a30d9 | 196 | #endif /* defined(ARCH_X86) */ |
783e9cc9 MN |
197 | |
198 | // clipping helper table for C implementations: | |
199 | static unsigned char clip_table[768]; | |
200 | ||
d4e24275 | 201 | static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b); |
6a4970ab | 202 | |
cf7d1c1a MN |
203 | extern const uint8_t dither_2x2_4[2][8]; |
204 | extern const uint8_t dither_2x2_8[2][8]; | |
205 | extern const uint8_t dither_8x8_32[8][8]; | |
206 | extern const uint8_t dither_8x8_73[8][8]; | |
207 | extern const uint8_t dither_8x8_220[8][8]; | |
5cebb24b | 208 | |
2d529db5 LA |
209 | static const char * sws_context_to_name(void * ptr) { |
210 | return "swscaler"; | |
211 | } | |
212 | ||
213 | static AVClass sws_context_class = { "SWScaler", sws_context_to_name, NULL }; | |
214 | ||
e9e12f0e | 215 | char *sws_format_name(enum PixelFormat format) |
94c4def2 | 216 | { |
e9e12f0e LA |
217 | switch (format) { |
218 | case PIX_FMT_YUV420P: | |
219 | return "yuv420p"; | |
220 | case PIX_FMT_YUYV422: | |
221 | return "yuyv422"; | |
222 | case PIX_FMT_RGB24: | |
223 | return "rgb24"; | |
224 | case PIX_FMT_BGR24: | |
225 | return "bgr24"; | |
226 | case PIX_FMT_YUV422P: | |
227 | return "yuv422p"; | |
228 | case PIX_FMT_YUV444P: | |
229 | return "yuv444p"; | |
230 | case PIX_FMT_RGB32: | |
231 | return "rgb32"; | |
232 | case PIX_FMT_YUV410P: | |
233 | return "yuv410p"; | |
234 | case PIX_FMT_YUV411P: | |
235 | return "yuv411p"; | |
236 | case PIX_FMT_RGB565: | |
237 | return "rgb565"; | |
238 | case PIX_FMT_RGB555: | |
239 | return "rgb555"; | |
4884b9e5 KS |
240 | case PIX_FMT_GRAY16BE: |
241 | return "gray16be"; | |
242 | case PIX_FMT_GRAY16LE: | |
243 | return "gray16le"; | |
e9e12f0e LA |
244 | case PIX_FMT_GRAY8: |
245 | return "gray8"; | |
246 | case PIX_FMT_MONOWHITE: | |
247 | return "mono white"; | |
248 | case PIX_FMT_MONOBLACK: | |
249 | return "mono black"; | |
250 | case PIX_FMT_PAL8: | |
251 | return "Palette"; | |
252 | case PIX_FMT_YUVJ420P: | |
253 | return "yuvj420p"; | |
254 | case PIX_FMT_YUVJ422P: | |
255 | return "yuvj422p"; | |
256 | case PIX_FMT_YUVJ444P: | |
257 | return "yuvj444p"; | |
258 | case PIX_FMT_XVMC_MPEG2_MC: | |
259 | return "xvmc_mpeg2_mc"; | |
260 | case PIX_FMT_XVMC_MPEG2_IDCT: | |
261 | return "xvmc_mpeg2_idct"; | |
262 | case PIX_FMT_UYVY422: | |
263 | return "uyvy422"; | |
264 | case PIX_FMT_UYYVYY411: | |
265 | return "uyyvyy411"; | |
266 | case PIX_FMT_RGB32_1: | |
267 | return "rgb32x"; | |
268 | case PIX_FMT_BGR32_1: | |
269 | return "bgr32x"; | |
270 | case PIX_FMT_BGR32: | |
271 | return "bgr32"; | |
272 | case PIX_FMT_BGR565: | |
273 | return "bgr565"; | |
274 | case PIX_FMT_BGR555: | |
275 | return "bgr555"; | |
276 | case PIX_FMT_BGR8: | |
277 | return "bgr8"; | |
278 | case PIX_FMT_BGR4: | |
279 | return "bgr4"; | |
280 | case PIX_FMT_BGR4_BYTE: | |
281 | return "bgr4 byte"; | |
282 | case PIX_FMT_RGB8: | |
283 | return "rgb8"; | |
284 | case PIX_FMT_RGB4: | |
285 | return "rgb4"; | |
286 | case PIX_FMT_RGB4_BYTE: | |
287 | return "rgb4 byte"; | |
288 | case PIX_FMT_NV12: | |
289 | return "nv12"; | |
290 | case PIX_FMT_NV21: | |
291 | return "nv21"; | |
292 | default: | |
293 | return "Unknown format"; | |
294 | } | |
94c4def2 LA |
295 | } |
296 | ||
9bde778e | 297 | #if defined(ARCH_X86) && defined (CONFIG_GPL) |
96034638 MN |
298 | void in_asm_used_var_warning_killer() |
299 | { | |
20380eb8 | 300 | volatile int i= bF8+bFC+w10+ |
5ac80202 | 301 | bm00001111+bm00000111+bm11111000+b16Mask+g16Mask+r16Mask+b15Mask+g15Mask+r15Mask+ |
6ff0ad6b | 302 | M24A+M24B+M24C+w02 + b5Dither+g5Dither+r5Dither+g6Dither+dither4[0]+dither8[0]+bm01010101; |
96034638 MN |
303 | if(i) i=0; |
304 | } | |
305 | #endif | |
d604bab9 | 306 | |
5859233b | 307 | static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, |
e3d2500f | 308 | int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, |
5859233b | 309 | uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW) |
e3d2500f MN |
310 | { |
311 | //FIXME Optimize (just quickly writen not opti..) | |
312 | int i; | |
5859233b | 313 | for(i=0; i<dstW; i++) |
e3d2500f | 314 | { |
379a2036 | 315 | int val=1<<18; |
e3d2500f MN |
316 | int j; |
317 | for(j=0; j<lumFilterSize; j++) | |
318 | val += lumSrc[j][i] * lumFilter[j]; | |
319 | ||
adcec46a | 320 | dest[i]= av_clip_uint8(val>>19); |
e3d2500f MN |
321 | } |
322 | ||
323 | if(uDest != NULL) | |
5859233b | 324 | for(i=0; i<chrDstW; i++) |
e3d2500f | 325 | { |
379a2036 MN |
326 | int u=1<<18; |
327 | int v=1<<18; | |
e3d2500f | 328 | int j; |
627690b5 | 329 | for(j=0; j<chrFilterSize; j++) |
e3d2500f MN |
330 | { |
331 | u += chrSrc[j][i] * chrFilter[j]; | |
332 | v += chrSrc[j][i + 2048] * chrFilter[j]; | |
333 | } | |
334 | ||
adcec46a RD |
335 | uDest[i]= av_clip_uint8(u>>19); |
336 | vDest[i]= av_clip_uint8(v>>19); | |
e3d2500f MN |
337 | } |
338 | } | |
339 | ||
6118e52e VS |
340 | static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, |
341 | int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, | |
342 | uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat) | |
343 | { | |
344 | //FIXME Optimize (just quickly writen not opti..) | |
345 | int i; | |
346 | for(i=0; i<dstW; i++) | |
347 | { | |
348 | int val=1<<18; | |
349 | int j; | |
350 | for(j=0; j<lumFilterSize; j++) | |
351 | val += lumSrc[j][i] * lumFilter[j]; | |
352 | ||
adcec46a | 353 | dest[i]= av_clip_uint8(val>>19); |
6118e52e VS |
354 | } |
355 | ||
356 | if(uDest == NULL) | |
357 | return; | |
358 | ||
e9e12f0e | 359 | if(dstFormat == PIX_FMT_NV12) |
6118e52e VS |
360 | for(i=0; i<chrDstW; i++) |
361 | { | |
362 | int u=1<<18; | |
363 | int v=1<<18; | |
364 | int j; | |
365 | for(j=0; j<chrFilterSize; j++) | |
366 | { | |
367 | u += chrSrc[j][i] * chrFilter[j]; | |
368 | v += chrSrc[j][i + 2048] * chrFilter[j]; | |
369 | } | |
370 | ||
adcec46a RD |
371 | uDest[2*i]= av_clip_uint8(u>>19); |
372 | uDest[2*i+1]= av_clip_uint8(v>>19); | |
6118e52e VS |
373 | } |
374 | else | |
375 | for(i=0; i<chrDstW; i++) | |
376 | { | |
377 | int u=1<<18; | |
378 | int v=1<<18; | |
379 | int j; | |
380 | for(j=0; j<chrFilterSize; j++) | |
381 | { | |
382 | u += chrSrc[j][i] * chrFilter[j]; | |
383 | v += chrSrc[j][i + 2048] * chrFilter[j]; | |
384 | } | |
385 | ||
adcec46a RD |
386 | uDest[2*i]= av_clip_uint8(v>>19); |
387 | uDest[2*i+1]= av_clip_uint8(u>>19); | |
6118e52e VS |
388 | } |
389 | } | |
46de8b73 | 390 | |
25593e29 | 391 | #define YSCALE_YUV_2_PACKEDX_C(type) \ |
cf7d1c1a MN |
392 | for(i=0; i<(dstW>>1); i++){\ |
393 | int j;\ | |
379a2036 MN |
394 | int Y1=1<<18;\ |
395 | int Y2=1<<18;\ | |
396 | int U=1<<18;\ | |
397 | int V=1<<18;\ | |
789237ca | 398 | type attribute_unused *r, *b, *g;\ |
cf7d1c1a MN |
399 | const int i2= 2*i;\ |
400 | \ | |
401 | for(j=0; j<lumFilterSize; j++)\ | |
402 | {\ | |
403 | Y1 += lumSrc[j][i2] * lumFilter[j];\ | |
404 | Y2 += lumSrc[j][i2+1] * lumFilter[j];\ | |
405 | }\ | |
406 | for(j=0; j<chrFilterSize; j++)\ | |
407 | {\ | |
408 | U += chrSrc[j][i] * chrFilter[j];\ | |
409 | V += chrSrc[j][i+2048] * chrFilter[j];\ | |
410 | }\ | |
411 | Y1>>=19;\ | |
412 | Y2>>=19;\ | |
413 | U >>=19;\ | |
414 | V >>=19;\ | |
415 | if((Y1|Y2|U|V)&256)\ | |
416 | {\ | |
417 | if(Y1>255) Y1=255;\ | |
418 | else if(Y1<0)Y1=0;\ | |
419 | if(Y2>255) Y2=255;\ | |
420 | else if(Y2<0)Y2=0;\ | |
421 | if(U>255) U=255;\ | |
422 | else if(U<0) U=0;\ | |
423 | if(V>255) V=255;\ | |
424 | else if(V<0) V=0;\ | |
46de8b73 | 425 | } |
6a4970ab | 426 | |
46de8b73 | 427 | #define YSCALE_YUV_2_RGBX_C(type) \ |
25593e29 | 428 | YSCALE_YUV_2_PACKEDX_C(type)\ |
628bc5e8 LA |
429 | r = (type *)c->table_rV[V];\ |
430 | g = (type *)(c->table_gU[U] + c->table_gV[V]);\ | |
431 | b = (type *)c->table_bU[U];\ | |
cf7d1c1a | 432 | |
25593e29 | 433 | #define YSCALE_YUV_2_PACKED2_C \ |
cf7d1c1a MN |
434 | for(i=0; i<(dstW>>1); i++){\ |
435 | const int i2= 2*i;\ | |
436 | int Y1= (buf0[i2 ]*yalpha1+buf1[i2 ]*yalpha)>>19;\ | |
437 | int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>19;\ | |
438 | int U= (uvbuf0[i ]*uvalpha1+uvbuf1[i ]*uvalpha)>>19;\ | |
439 | int V= (uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>19;\ | |
46de8b73 MN |
440 | |
441 | #define YSCALE_YUV_2_RGB2_C(type) \ | |
25593e29 | 442 | YSCALE_YUV_2_PACKED2_C\ |
cf7d1c1a | 443 | type *r, *b, *g;\ |
628bc5e8 LA |
444 | r = (type *)c->table_rV[V];\ |
445 | g = (type *)(c->table_gU[U] + c->table_gV[V]);\ | |
446 | b = (type *)c->table_bU[U];\ | |
cf7d1c1a | 447 | |
25593e29 | 448 | #define YSCALE_YUV_2_PACKED1_C \ |
cf7d1c1a MN |
449 | for(i=0; i<(dstW>>1); i++){\ |
450 | const int i2= 2*i;\ | |
451 | int Y1= buf0[i2 ]>>7;\ | |
452 | int Y2= buf0[i2+1]>>7;\ | |
453 | int U= (uvbuf1[i ])>>7;\ | |
454 | int V= (uvbuf1[i+2048])>>7;\ | |
46de8b73 MN |
455 | |
456 | #define YSCALE_YUV_2_RGB1_C(type) \ | |
25593e29 | 457 | YSCALE_YUV_2_PACKED1_C\ |
cf7d1c1a | 458 | type *r, *b, *g;\ |
628bc5e8 LA |
459 | r = (type *)c->table_rV[V];\ |
460 | g = (type *)(c->table_gU[U] + c->table_gV[V]);\ | |
461 | b = (type *)c->table_bU[U];\ | |
cf7d1c1a | 462 | |
25593e29 | 463 | #define YSCALE_YUV_2_PACKED1B_C \ |
cf7d1c1a MN |
464 | for(i=0; i<(dstW>>1); i++){\ |
465 | const int i2= 2*i;\ | |
466 | int Y1= buf0[i2 ]>>7;\ | |
467 | int Y2= buf0[i2+1]>>7;\ | |
468 | int U= (uvbuf0[i ] + uvbuf1[i ])>>8;\ | |
469 | int V= (uvbuf0[i+2048] + uvbuf1[i+2048])>>8;\ | |
46de8b73 MN |
470 | |
471 | #define YSCALE_YUV_2_RGB1B_C(type) \ | |
25593e29 | 472 | YSCALE_YUV_2_PACKED1B_C\ |
cf7d1c1a | 473 | type *r, *b, *g;\ |
628bc5e8 LA |
474 | r = (type *)c->table_rV[V];\ |
475 | g = (type *)(c->table_gU[U] + c->table_gV[V]);\ | |
476 | b = (type *)c->table_bU[U];\ | |
cf7d1c1a | 477 | |
46de8b73 | 478 | #define YSCALE_YUV_2_ANYRGB_C(func, func2)\ |
cf7d1c1a MN |
479 | switch(c->dstFormat)\ |
480 | {\ | |
e9e12f0e LA |
481 | case PIX_FMT_RGB32:\ |
482 | case PIX_FMT_BGR32:\ | |
cf7d1c1a MN |
483 | func(uint32_t)\ |
484 | ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\ | |
485 | ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\ | |
486 | } \ | |
487 | break;\ | |
e9e12f0e | 488 | case PIX_FMT_RGB24:\ |
cf7d1c1a MN |
489 | func(uint8_t)\ |
490 | ((uint8_t*)dest)[0]= r[Y1];\ | |
491 | ((uint8_t*)dest)[1]= g[Y1];\ | |
492 | ((uint8_t*)dest)[2]= b[Y1];\ | |
493 | ((uint8_t*)dest)[3]= r[Y2];\ | |
494 | ((uint8_t*)dest)[4]= g[Y2];\ | |
495 | ((uint8_t*)dest)[5]= b[Y2];\ | |
ae4cffd9 | 496 | dest+=6;\ |
cf7d1c1a MN |
497 | }\ |
498 | break;\ | |
e9e12f0e | 499 | case PIX_FMT_BGR24:\ |
cf7d1c1a MN |
500 | func(uint8_t)\ |
501 | ((uint8_t*)dest)[0]= b[Y1];\ | |
502 | ((uint8_t*)dest)[1]= g[Y1];\ | |
503 | ((uint8_t*)dest)[2]= r[Y1];\ | |
504 | ((uint8_t*)dest)[3]= b[Y2];\ | |
505 | ((uint8_t*)dest)[4]= g[Y2];\ | |
506 | ((uint8_t*)dest)[5]= r[Y2];\ | |
ae4cffd9 | 507 | dest+=6;\ |
cf7d1c1a MN |
508 | }\ |
509 | break;\ | |
e9e12f0e LA |
510 | case PIX_FMT_RGB565:\ |
511 | case PIX_FMT_BGR565:\ | |
cf7d1c1a MN |
512 | {\ |
513 | const int dr1= dither_2x2_8[y&1 ][0];\ | |
514 | const int dg1= dither_2x2_4[y&1 ][0];\ | |
515 | const int db1= dither_2x2_8[(y&1)^1][0];\ | |
516 | const int dr2= dither_2x2_8[y&1 ][1];\ | |
517 | const int dg2= dither_2x2_4[y&1 ][1];\ | |
518 | const int db2= dither_2x2_8[(y&1)^1][1];\ | |
519 | func(uint16_t)\ | |
520 | ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\ | |
521 | ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\ | |
522 | }\ | |
523 | }\ | |
524 | break;\ | |
e9e12f0e LA |
525 | case PIX_FMT_RGB555:\ |
526 | case PIX_FMT_BGR555:\ | |
cf7d1c1a MN |
527 | {\ |
528 | const int dr1= dither_2x2_8[y&1 ][0];\ | |
529 | const int dg1= dither_2x2_8[y&1 ][1];\ | |
530 | const int db1= dither_2x2_8[(y&1)^1][0];\ | |
531 | const int dr2= dither_2x2_8[y&1 ][1];\ | |
532 | const int dg2= dither_2x2_8[y&1 ][0];\ | |
533 | const int db2= dither_2x2_8[(y&1)^1][1];\ | |
534 | func(uint16_t)\ | |
535 | ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\ | |
536 | ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\ | |
537 | }\ | |
538 | }\ | |
539 | break;\ | |
e9e12f0e LA |
540 | case PIX_FMT_RGB8:\ |
541 | case PIX_FMT_BGR8:\ | |
cf7d1c1a MN |
542 | {\ |
543 | const uint8_t * const d64= dither_8x8_73[y&7];\ | |
544 | const uint8_t * const d32= dither_8x8_32[y&7];\ | |
545 | func(uint8_t)\ | |
546 | ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];\ | |
547 | ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];\ | |
548 | }\ | |
549 | }\ | |
550 | break;\ | |
e9e12f0e LA |
551 | case PIX_FMT_RGB4:\ |
552 | case PIX_FMT_BGR4:\ | |
cf7d1c1a MN |
553 | {\ |
554 | const uint8_t * const d64= dither_8x8_73 [y&7];\ | |
555 | const uint8_t * const d128=dither_8x8_220[y&7];\ | |
556 | func(uint8_t)\ | |
799fd467 | 557 | ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]\ |
f17457ac MN |
558 | + ((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);\ |
559 | }\ | |
560 | }\ | |
561 | break;\ | |
e9e12f0e LA |
562 | case PIX_FMT_RGB4_BYTE:\ |
563 | case PIX_FMT_BGR4_BYTE:\ | |
f17457ac MN |
564 | {\ |
565 | const uint8_t * const d64= dither_8x8_73 [y&7];\ | |
566 | const uint8_t * const d128=dither_8x8_220[y&7];\ | |
567 | func(uint8_t)\ | |
cf7d1c1a MN |
568 | ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];\ |
569 | ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];\ | |
570 | }\ | |
571 | }\ | |
572 | break;\ | |
e9e12f0e | 573 | case PIX_FMT_MONOBLACK:\ |
cf7d1c1a MN |
574 | {\ |
575 | const uint8_t * const d128=dither_8x8_220[y&7];\ | |
576 | uint8_t *g= c->table_gU[128] + c->table_gV[128];\ | |
577 | for(i=0; i<dstW-7; i+=8){\ | |
578 | int acc;\ | |
579 | acc = g[((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19) + d128[0]];\ | |
580 | acc+= acc + g[((buf0[i+1]*yalpha1+buf1[i+1]*yalpha)>>19) + d128[1]];\ | |
581 | acc+= acc + g[((buf0[i+2]*yalpha1+buf1[i+2]*yalpha)>>19) + d128[2]];\ | |
582 | acc+= acc + g[((buf0[i+3]*yalpha1+buf1[i+3]*yalpha)>>19) + d128[3]];\ | |
583 | acc+= acc + g[((buf0[i+4]*yalpha1+buf1[i+4]*yalpha)>>19) + d128[4]];\ | |
584 | acc+= acc + g[((buf0[i+5]*yalpha1+buf1[i+5]*yalpha)>>19) + d128[5]];\ | |
585 | acc+= acc + g[((buf0[i+6]*yalpha1+buf1[i+6]*yalpha)>>19) + d128[6]];\ | |
586 | acc+= acc + g[((buf0[i+7]*yalpha1+buf1[i+7]*yalpha)>>19) + d128[7]];\ | |
587 | ((uint8_t*)dest)[0]= acc;\ | |
ae4cffd9 | 588 | dest++;\ |
cf7d1c1a MN |
589 | }\ |
590 | \ | |
591 | /*\ | |
592 | ((uint8_t*)dest)-= dstW>>4;\ | |
593 | {\ | |
594 | int acc=0;\ | |
595 | int left=0;\ | |
596 | static int top[1024];\ | |
597 | static int last_new[1024][1024];\ | |
598 | static int last_in3[1024][1024];\ | |
599 | static int drift[1024][1024];\ | |
600 | int topLeft=0;\ | |
601 | int shift=0;\ | |
602 | int count=0;\ | |
603 | const uint8_t * const d128=dither_8x8_220[y&7];\ | |
604 | int error_new=0;\ | |
605 | int error_in3=0;\ | |
606 | int f=0;\ | |
607 | \ | |
608 | for(i=dstW>>1; i<dstW; i++){\ | |
609 | int in= ((buf0[i ]*yalpha1+buf1[i ]*yalpha)>>19);\ | |
610 | int in2 = (76309 * (in - 16) + 32768) >> 16;\ | |
611 | int in3 = (in2 < 0) ? 0 : ((in2 > 255) ? 255 : in2);\ | |
612 | int old= (left*7 + topLeft + top[i]*5 + top[i+1]*3)/20 + in3\ | |
613 | + (last_new[y][i] - in3)*f/256;\ | |
614 | int new= old> 128 ? 255 : 0;\ | |
615 | \ | |
05749630 DB |
616 | error_new+= FFABS(last_new[y][i] - new);\ |
617 | error_in3+= FFABS(last_in3[y][i] - in3);\ | |
cf7d1c1a MN |
618 | f= error_new - error_in3*4;\ |
619 | if(f<0) f=0;\ | |
620 | if(f>256) f=256;\ | |
621 | \ | |
622 | topLeft= top[i];\ | |
623 | left= top[i]= old - new;\ | |
624 | last_new[y][i]= new;\ | |
625 | last_in3[y][i]= in3;\ | |
626 | \ | |
627 | acc+= acc + (new&1);\ | |
628 | if((i&7)==6){\ | |
629 | ((uint8_t*)dest)[0]= acc;\ | |
630 | ((uint8_t*)dest)++;\ | |
631 | }\ | |
632 | }\ | |
633 | }\ | |
634 | */\ | |
635 | }\ | |
636 | break;\ | |
e9e12f0e | 637 | case PIX_FMT_YUYV422:\ |
46de8b73 MN |
638 | func2\ |
639 | ((uint8_t*)dest)[2*i2+0]= Y1;\ | |
640 | ((uint8_t*)dest)[2*i2+1]= U;\ | |
641 | ((uint8_t*)dest)[2*i2+2]= Y2;\ | |
642 | ((uint8_t*)dest)[2*i2+3]= V;\ | |
643 | } \ | |
644 | break;\ | |
e9e12f0e | 645 | case PIX_FMT_UYVY422:\ |
caeaabe7 AB |
646 | func2\ |
647 | ((uint8_t*)dest)[2*i2+0]= U;\ | |
648 | ((uint8_t*)dest)[2*i2+1]= Y1;\ | |
649 | ((uint8_t*)dest)[2*i2+2]= V;\ | |
650 | ((uint8_t*)dest)[2*i2+3]= Y2;\ | |
651 | } \ | |
652 | break;\ | |
cf7d1c1a MN |
653 | }\ |
654 | ||
655 | ||
25593e29 | 656 | static inline void yuv2packedXinC(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, |
e3d2500f | 657 | int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, |
cf7d1c1a | 658 | uint8_t *dest, int dstW, int y) |
e3d2500f | 659 | { |
cf7d1c1a MN |
660 | int i; |
661 | switch(c->dstFormat) | |
e3d2500f | 662 | { |
e9e12f0e LA |
663 | case PIX_FMT_BGR32: |
664 | case PIX_FMT_RGB32: | |
cf7d1c1a MN |
665 | YSCALE_YUV_2_RGBX_C(uint32_t) |
666 | ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1]; | |
667 | ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2]; | |
e3d2500f | 668 | } |
cf7d1c1a | 669 | break; |
e9e12f0e | 670 | case PIX_FMT_RGB24: |
cf7d1c1a MN |
671 | YSCALE_YUV_2_RGBX_C(uint8_t) |
672 | ((uint8_t*)dest)[0]= r[Y1]; | |
673 | ((uint8_t*)dest)[1]= g[Y1]; | |
674 | ((uint8_t*)dest)[2]= b[Y1]; | |
675 | ((uint8_t*)dest)[3]= r[Y2]; | |
676 | ((uint8_t*)dest)[4]= g[Y2]; | |
677 | ((uint8_t*)dest)[5]= b[Y2]; | |
ae4cffd9 | 678 | dest+=6; |
cf7d1c1a MN |
679 | } |
680 | break; | |
e9e12f0e | 681 | case PIX_FMT_BGR24: |
cf7d1c1a MN |
682 | YSCALE_YUV_2_RGBX_C(uint8_t) |
683 | ((uint8_t*)dest)[0]= b[Y1]; | |
684 | ((uint8_t*)dest)[1]= g[Y1]; | |
685 | ((uint8_t*)dest)[2]= r[Y1]; | |
686 | ((uint8_t*)dest)[3]= b[Y2]; | |
687 | ((uint8_t*)dest)[4]= g[Y2]; | |
688 | ((uint8_t*)dest)[5]= r[Y2]; | |
ae4cffd9 | 689 | dest+=6; |
cf7d1c1a MN |
690 | } |
691 | break; | |
e9e12f0e LA |
692 | case PIX_FMT_RGB565: |
693 | case PIX_FMT_BGR565: | |
cf7d1c1a MN |
694 | { |
695 | const int dr1= dither_2x2_8[y&1 ][0]; | |
696 | const int dg1= dither_2x2_4[y&1 ][0]; | |
697 | const int db1= dither_2x2_8[(y&1)^1][0]; | |
698 | const int dr2= dither_2x2_8[y&1 ][1]; | |
699 | const int dg2= dither_2x2_4[y&1 ][1]; | |
700 | const int db2= dither_2x2_8[(y&1)^1][1]; | |
701 | YSCALE_YUV_2_RGBX_C(uint16_t) | |
702 | ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1]; | |
703 | ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2]; | |
e3d2500f | 704 | } |
e3d2500f | 705 | } |
cf7d1c1a | 706 | break; |
e9e12f0e LA |
707 | case PIX_FMT_RGB555: |
708 | case PIX_FMT_BGR555: | |
cf7d1c1a MN |
709 | { |
710 | const int dr1= dither_2x2_8[y&1 ][0]; | |
711 | const int dg1= dither_2x2_8[y&1 ][1]; | |
712 | const int db1= dither_2x2_8[(y&1)^1][0]; | |
713 | const int dr2= dither_2x2_8[y&1 ][1]; | |
714 | const int dg2= dither_2x2_8[y&1 ][0]; | |
715 | const int db2= dither_2x2_8[(y&1)^1][1]; | |
716 | YSCALE_YUV_2_RGBX_C(uint16_t) | |
717 | ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1]; | |
718 | ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2]; | |
e3d2500f | 719 | } |
cf7d1c1a MN |
720 | } |
721 | break; | |
e9e12f0e LA |
722 | case PIX_FMT_RGB8: |
723 | case PIX_FMT_BGR8: | |
cf7d1c1a MN |
724 | { |
725 | const uint8_t * const d64= dither_8x8_73[y&7]; | |
726 | const uint8_t * const d32= dither_8x8_32[y&7]; | |
727 | YSCALE_YUV_2_RGBX_C(uint8_t) | |
728 | ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]]; | |
729 | ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]]; | |
e3d2500f | 730 | } |
e3d2500f | 731 | } |
cf7d1c1a | 732 | break; |
e9e12f0e LA |
733 | case PIX_FMT_RGB4: |
734 | case PIX_FMT_BGR4: | |
cf7d1c1a MN |
735 | { |
736 | const uint8_t * const d64= dither_8x8_73 [y&7]; | |
737 | const uint8_t * const d128=dither_8x8_220[y&7]; | |
738 | YSCALE_YUV_2_RGBX_C(uint8_t) | |
799fd467 | 739 | ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]] |
f17457ac MN |
740 | +((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4); |
741 | } | |
742 | } | |
743 | break; | |
e9e12f0e LA |
744 | case PIX_FMT_RGB4_BYTE: |
745 | case PIX_FMT_BGR4_BYTE: | |
f17457ac MN |
746 | { |
747 | const uint8_t * const d64= dither_8x8_73 [y&7]; | |
748 | const uint8_t * const d128=dither_8x8_220[y&7]; | |
749 | YSCALE_YUV_2_RGBX_C(uint8_t) | |
cf7d1c1a MN |
750 | ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]; |
751 | ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]]; | |
e3d2500f | 752 | } |
cf7d1c1a MN |
753 | } |
754 | break; | |
e9e12f0e | 755 | case PIX_FMT_MONOBLACK: |
cf7d1c1a MN |
756 | { |
757 | const uint8_t * const d128=dither_8x8_220[y&7]; | |
758 | uint8_t *g= c->table_gU[128] + c->table_gV[128]; | |
759 | int acc=0; | |
760 | for(i=0; i<dstW-1; i+=2){ | |
761 | int j; | |
379a2036 MN |
762 | int Y1=1<<18; |
763 | int Y2=1<<18; | |
cf7d1c1a MN |
764 | |
765 | for(j=0; j<lumFilterSize; j++) | |
766 | { | |
767 | Y1 += lumSrc[j][i] * lumFilter[j]; | |
768 | Y2 += lumSrc[j][i+1] * lumFilter[j]; | |
769 | } | |
770 | Y1>>=19; | |
771 | Y2>>=19; | |
772 | if((Y1|Y2)&256) | |
773 | { | |
774 | if(Y1>255) Y1=255; | |
775 | else if(Y1<0)Y1=0; | |
776 | if(Y2>255) Y2=255; | |
777 | else if(Y2<0)Y2=0; | |
778 | } | |
779 | acc+= acc + g[Y1+d128[(i+0)&7]]; | |
780 | acc+= acc + g[Y2+d128[(i+1)&7]]; | |
781 | if((i&7)==6){ | |
782 | ((uint8_t*)dest)[0]= acc; | |
ae4cffd9 | 783 | dest++; |
cf7d1c1a | 784 | } |
e3d2500f | 785 | } |
e3d2500f | 786 | } |
cf7d1c1a | 787 | break; |
e9e12f0e | 788 | case PIX_FMT_YUYV422: |
25593e29 | 789 | YSCALE_YUV_2_PACKEDX_C(void) |
46de8b73 MN |
790 | ((uint8_t*)dest)[2*i2+0]= Y1; |
791 | ((uint8_t*)dest)[2*i2+1]= U; | |
792 | ((uint8_t*)dest)[2*i2+2]= Y2; | |
793 | ((uint8_t*)dest)[2*i2+3]= V; | |
794 | } | |
795 | break; | |
e9e12f0e | 796 | case PIX_FMT_UYVY422: |
caeaabe7 AB |
797 | YSCALE_YUV_2_PACKEDX_C(void) |
798 | ((uint8_t*)dest)[2*i2+0]= U; | |
799 | ((uint8_t*)dest)[2*i2+1]= Y1; | |
800 | ((uint8_t*)dest)[2*i2+2]= V; | |
801 | ((uint8_t*)dest)[2*i2+3]= Y2; | |
802 | } | |
803 | break; | |
e3d2500f MN |
804 | } |
805 | } | |
806 | ||
807 | ||
7630f2e0 MN |
808 | //Note: we have C, X86, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one |
809 | //Plain C versions | |
9bde778e | 810 | #if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT) || !defined(CONFIG_GPL) |
726a959a MN |
811 | #define COMPILE_C |
812 | #endif | |
813 | ||
a2faa401 | 814 | #ifdef ARCH_POWERPC |
9bde778e | 815 | #if (defined (HAVE_ALTIVEC) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL) |
a2faa401 RD |
816 | #define COMPILE_ALTIVEC |
817 | #endif //HAVE_ALTIVEC | |
818 | #endif //ARCH_POWERPC | |
819 | ||
3d6a30d9 | 820 | #if defined(ARCH_X86) |
726a959a | 821 | |
9bde778e | 822 | #if ((defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL) |
726a959a MN |
823 | #define COMPILE_MMX |
824 | #endif | |
825 | ||
9bde778e | 826 | #if (defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL) |
726a959a MN |
827 | #define COMPILE_MMX2 |
828 | #endif | |
829 | ||
9bde778e | 830 | #if ((defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT)) && defined (CONFIG_GPL) |
726a959a MN |
831 | #define COMPILE_3DNOW |
832 | #endif | |
6e1c66bc | 833 | #endif //ARCH_X86 || ARCH_X86_64 |
726a959a MN |
834 | |
835 | #undef HAVE_MMX | |
836 | #undef HAVE_MMX2 | |
837 | #undef HAVE_3DNOW | |
726a959a MN |
838 | |
839 | #ifdef COMPILE_C | |
7630f2e0 MN |
840 | #undef HAVE_MMX |
841 | #undef HAVE_MMX2 | |
842 | #undef HAVE_3DNOW | |
a2faa401 | 843 | #undef HAVE_ALTIVEC |
7630f2e0 MN |
844 | #define RENAME(a) a ## _C |
845 | #include "swscale_template.c" | |
726a959a | 846 | #endif |
397c035e | 847 | |
a2faa401 RD |
848 | #ifdef ARCH_POWERPC |
849 | #ifdef COMPILE_ALTIVEC | |
850 | #undef RENAME | |
851 | #define HAVE_ALTIVEC | |
852 | #define RENAME(a) a ## _altivec | |
853 | #include "swscale_template.c" | |
854 | #endif | |
855 | #endif //ARCH_POWERPC | |
856 | ||
3d6a30d9 | 857 | #if defined(ARCH_X86) |
397c035e | 858 | |
7630f2e0 MN |
859 | //X86 versions |
860 | /* | |
861 | #undef RENAME | |
862 | #undef HAVE_MMX | |
863 | #undef HAVE_MMX2 | |
864 | #undef HAVE_3DNOW | |
865 | #define ARCH_X86 | |
866 | #define RENAME(a) a ## _X86 | |
867 | #include "swscale_template.c" | |
1faf0867 | 868 | */ |
7630f2e0 | 869 | //MMX versions |
726a959a | 870 | #ifdef COMPILE_MMX |
7630f2e0 MN |
871 | #undef RENAME |
872 | #define HAVE_MMX | |
873 | #undef HAVE_MMX2 | |
874 | #undef HAVE_3DNOW | |
7630f2e0 MN |
875 | #define RENAME(a) a ## _MMX |
876 | #include "swscale_template.c" | |
726a959a | 877 | #endif |
7630f2e0 MN |
878 | |
879 | //MMX2 versions | |
726a959a | 880 | #ifdef COMPILE_MMX2 |
7630f2e0 MN |
881 | #undef RENAME |
882 | #define HAVE_MMX | |
883 | #define HAVE_MMX2 | |
884 | #undef HAVE_3DNOW | |
7630f2e0 MN |
885 | #define RENAME(a) a ## _MMX2 |
886 | #include "swscale_template.c" | |
726a959a | 887 | #endif |
7630f2e0 MN |
888 | |
889 | //3DNOW versions | |
726a959a | 890 | #ifdef COMPILE_3DNOW |
7630f2e0 MN |
891 | #undef RENAME |
892 | #define HAVE_MMX | |
893 | #undef HAVE_MMX2 | |
894 | #define HAVE_3DNOW | |
7630f2e0 MN |
895 | #define RENAME(a) a ## _3DNow |
896 | #include "swscale_template.c" | |
726a959a | 897 | #endif |
7630f2e0 | 898 | |
6e1c66bc | 899 | #endif //ARCH_X86 || ARCH_X86_64 |
7630f2e0 | 900 | |
77a416e8 | 901 | // minor note: the HAVE_xyz is messed up after that line so don't use it |
d604bab9 | 902 | |
a86c461c MN |
903 | static double getSplineCoeff(double a, double b, double c, double d, double dist) |
904 | { | |
905 | // printf("%f %f %f %f %f\n", a,b,c,d,dist); | |
906 | if(dist<=1.0) return ((d*dist + c)*dist + b)*dist +a; | |
6a4970ab | 907 | else return getSplineCoeff( 0.0, |
a86c461c MN |
908 | b+ 2.0*c + 3.0*d, |
909 | c + 3.0*d, | |
910 | -b- 3.0*c - 6.0*d, | |
911 | dist-1.0); | |
912 | } | |
6c7506de | 913 | |
bca11e75 | 914 | static inline int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc, |
c7f822d9 | 915 | int srcW, int dstW, int filterAlign, int one, int flags, |
66d1cdb6 | 916 | SwsVector *srcFilter, SwsVector *dstFilter, double param[2]) |
28bf81c9 MN |
917 | { |
918 | int i; | |
c7f822d9 MN |
919 | int filterSize; |
920 | int filter2Size; | |
921 | int minFilterSize; | |
922 | double *filter=NULL; | |
923 | double *filter2=NULL; | |
3d6a30d9 | 924 | #if defined(ARCH_X86) |
516b1f82 | 925 | if(flags & SWS_CPU_CAPS_MMX) |
28bf81c9 | 926 | asm volatile("emms\n\t"::: "memory"); //FIXME this shouldnt be required but it IS (even for non mmx versions) |
726a959a | 927 | #endif |
31190492 | 928 | |
adeaecb9 | 929 | // Note the +1 is for the MMXscaler which reads over the end |
8dfe9094 | 930 | *filterPos = av_malloc((dstW+1)*sizeof(int16_t)); |
6c7506de | 931 | |
05749630 | 932 | if(FFABS(xInc - 0x10000) <10) // unscaled |
28bf81c9 MN |
933 | { |
934 | int i; | |
c7f822d9 | 935 | filterSize= 1; |
8dfe9094 | 936 | filter= av_malloc(dstW*sizeof(double)*filterSize); |
c7f822d9 | 937 | for(i=0; i<dstW*filterSize; i++) filter[i]=0; |
28bf81c9 MN |
938 | |
939 | for(i=0; i<dstW; i++) | |
940 | { | |
c7f822d9 MN |
941 | filter[i*filterSize]=1; |
942 | (*filterPos)[i]=i; | |
28bf81c9 MN |
943 | } |
944 | ||
945 | } | |
ff7ba856 MN |
946 | else if(flags&SWS_POINT) // lame looking point sampling mode |
947 | { | |
948 | int i; | |
949 | int xDstInSrc; | |
950 | filterSize= 1; | |
8dfe9094 | 951 | filter= av_malloc(dstW*sizeof(double)*filterSize); |
6a4970ab | 952 | |
ff7ba856 MN |
953 | xDstInSrc= xInc/2 - 0x8000; |
954 | for(i=0; i<dstW; i++) | |
955 | { | |
8a01d20c | 956 | int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16; |
ff7ba856 MN |
957 | |
958 | (*filterPos)[i]= xx; | |
959 | filter[i]= 1.0; | |
960 | xDstInSrc+= xInc; | |
961 | } | |
962 | } | |
a86c461c | 963 | else if((xInc <= (1<<16) && (flags&SWS_AREA)) || (flags&SWS_FAST_BILINEAR)) // bilinear upscale |
28bf81c9 MN |
964 | { |
965 | int i; | |
966 | int xDstInSrc; | |
c7f822d9 MN |
967 | if (flags&SWS_BICUBIC) filterSize= 4; |
968 | else if(flags&SWS_X ) filterSize= 4; | |
6a4970ab | 969 | else filterSize= 2; // SWS_BILINEAR / SWS_AREA |
8dfe9094 | 970 | filter= av_malloc(dstW*sizeof(double)*filterSize); |
28bf81c9 MN |
971 | |
972 | xDstInSrc= xInc/2 - 0x8000; | |
973 | for(i=0; i<dstW; i++) | |
974 | { | |
8a01d20c | 975 | int xx= (xDstInSrc - ((filterSize-1)<<15) + (1<<15))>>16; |
28bf81c9 MN |
976 | int j; |
977 | ||
c7f822d9 | 978 | (*filterPos)[i]= xx; |
d8863d37 | 979 | //Bilinear upscale / linear interpolate / Area averaging |
c7f822d9 | 980 | for(j=0; j<filterSize; j++) |
28bf81c9 | 981 | { |
05749630 | 982 | double d= FFABS((xx<<16) - xDstInSrc)/(double)(1<<16); |
28bf81c9 MN |
983 | double coeff= 1.0 - d; |
984 | if(coeff<0) coeff=0; | |
c7f822d9 | 985 | filter[i*filterSize + j]= coeff; |
28bf81c9 MN |
986 | xx++; |
987 | } | |
28bf81c9 MN |
988 | xDstInSrc+= xInc; |
989 | } | |
990 | } | |
a86c461c | 991 | else |
28bf81c9 | 992 | { |
a86c461c MN |
993 | double xDstInSrc; |
994 | double sizeFactor, filterSizeInSrc; | |
995 | const double xInc1= (double)xInc / (double)(1<<16); | |
a86c461c MN |
996 | |
997 | if (flags&SWS_BICUBIC) sizeFactor= 4.0; | |
998 | else if(flags&SWS_X) sizeFactor= 8.0; | |
999 | else if(flags&SWS_AREA) sizeFactor= 1.0; //downscale only, for upscale it is bilinear | |
1000 | else if(flags&SWS_GAUSS) sizeFactor= 8.0; // infinite ;) | |
66d1cdb6 | 1001 | else if(flags&SWS_LANCZOS) sizeFactor= param[0] != SWS_PARAM_DEFAULT ? 2.0*param[0] : 6.0; |
93768378 | 1002 | else if(flags&SWS_SINC) sizeFactor= 20.0; // infinite ;) |
a86c461c MN |
1003 | else if(flags&SWS_SPLINE) sizeFactor= 20.0; // infinite ;) |
1004 | else if(flags&SWS_BILINEAR) sizeFactor= 2.0; | |
93768378 MN |
1005 | else { |
1006 | sizeFactor= 0.0; //GCC warning killer | |
1007 | ASSERT(0) | |
1008 | } | |
6a4970ab | 1009 | |
a86c461c MN |
1010 | if(xInc1 <= 1.0) filterSizeInSrc= sizeFactor; // upscale |
1011 | else filterSizeInSrc= sizeFactor*srcW / (double)dstW; | |
81b7c056 | 1012 | |
a86c461c MN |
1013 | filterSize= (int)ceil(1 + filterSizeInSrc); // will be reduced later if possible |
1014 | if(filterSize > srcW-2) filterSize=srcW-2; | |
28bf81c9 | 1015 | |
8dfe9094 | 1016 | filter= av_malloc(dstW*sizeof(double)*filterSize); |
a86c461c MN |
1017 | |
1018 | xDstInSrc= xInc1 / 2.0 - 0.5; | |
28bf81c9 MN |
1019 | for(i=0; i<dstW; i++) |
1020 | { | |
a86c461c | 1021 | int xx= (int)(xDstInSrc - (filterSize-1)*0.5 + 0.5); |
28bf81c9 | 1022 | int j; |
c7f822d9 MN |
1023 | (*filterPos)[i]= xx; |
1024 | for(j=0; j<filterSize; j++) | |
28bf81c9 | 1025 | { |
05749630 | 1026 | double d= FFABS(xx - xDstInSrc)/filterSizeInSrc*sizeFactor; |
28bf81c9 | 1027 | double coeff; |
a86c461c | 1028 | if(flags & SWS_BICUBIC) |
28bf81c9 | 1029 | { |
66d1cdb6 MN |
1030 | double B= param[0] != SWS_PARAM_DEFAULT ? param[0] : 0.0; |
1031 | double C= param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6; | |
1032 | ||
6a4970ab | 1033 | if(d<1.0) |
66d1cdb6 | 1034 | coeff = (12-9*B-6*C)*d*d*d + (-18+12*B+6*C)*d*d + 6-2*B; |
28bf81c9 | 1035 | else if(d<2.0) |
66d1cdb6 | 1036 | coeff = (-B-6*C)*d*d*d + (6*B+30*C)*d*d + (-12*B-48*C)*d +8*B+24*C; |
28bf81c9 MN |
1037 | else |
1038 | coeff=0.0; | |
1039 | } | |
a86c461c MN |
1040 | /* else if(flags & SWS_X) |
1041 | { | |
1042 | double p= param ? param*0.01 : 0.3; | |
1043 | coeff = d ? sin(d*PI)/(d*PI) : 1.0; | |
1044 | coeff*= pow(2.0, - p*d*d); | |
1045 | }*/ | |
1046 | else if(flags & SWS_X) | |
1047 | { | |
66d1cdb6 | 1048 | double A= param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0; |
6a4970ab | 1049 | |
a86c461c MN |
1050 | if(d<1.0) |
1051 | coeff = cos(d*PI); | |
1052 | else | |
1053 | coeff=-1.0; | |
1054 | if(coeff<0.0) coeff= -pow(-coeff, A); | |
1055 | else coeff= pow( coeff, A); | |
1056 | coeff= coeff*0.5 + 0.5; | |
1057 | } | |
d8863d37 | 1058 | else if(flags & SWS_AREA) |
28bf81c9 | 1059 | { |
a86c461c | 1060 | double srcPixelSize= 1.0/xInc1; |
d8863d37 MN |
1061 | if(d + srcPixelSize/2 < 0.5) coeff= 1.0; |
1062 | else if(d - srcPixelSize/2 < 0.5) coeff= (0.5-d)/srcPixelSize + 0.5; | |
1063 | else coeff=0.0; | |
1064 | } | |
a86c461c MN |
1065 | else if(flags & SWS_GAUSS) |
1066 | { | |
66d1cdb6 | 1067 | double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0; |
a86c461c MN |
1068 | coeff = pow(2.0, - p*d*d); |
1069 | } | |
1070 | else if(flags & SWS_SINC) | |
1071 | { | |
1072 | coeff = d ? sin(d*PI)/(d*PI) : 1.0; | |
1073 | } | |
1074 | else if(flags & SWS_LANCZOS) | |
1075 | { | |
6a4970ab | 1076 | double p= param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0; |
a86c461c MN |
1077 | coeff = d ? sin(d*PI)*sin(d*PI/p)/(d*d*PI*PI/p) : 1.0; |
1078 | if(d>p) coeff=0; | |
1079 | } | |
1080 | else if(flags & SWS_BILINEAR) | |
28bf81c9 MN |
1081 | { |
1082 | coeff= 1.0 - d; | |
1083 | if(coeff<0) coeff=0; | |
1084 | } | |
a86c461c MN |
1085 | else if(flags & SWS_SPLINE) |
1086 | { | |
1087 | double p=-2.196152422706632; | |
1088 | coeff = getSplineCoeff(1.0, 0.0, p, -p-1.0, d); | |
1089 | } | |
93768378 MN |
1090 | else { |
1091 | coeff= 0.0; //GCC warning killer | |
1092 | ASSERT(0) | |
1093 | } | |
a86c461c | 1094 | |
c7f822d9 | 1095 | filter[i*filterSize + j]= coeff; |
28bf81c9 MN |
1096 | xx++; |
1097 | } | |
a86c461c | 1098 | xDstInSrc+= xInc1; |
28bf81c9 MN |
1099 | } |
1100 | } | |
1101 | ||
c7f822d9 | 1102 | /* apply src & dst Filter to filter -> filter2 |
94c4def2 | 1103 | av_free(filter); |
c7f822d9 | 1104 | */ |
81b7c056 | 1105 | ASSERT(filterSize>0) |
c7f822d9 MN |
1106 | filter2Size= filterSize; |
1107 | if(srcFilter) filter2Size+= srcFilter->length - 1; | |
1108 | if(dstFilter) filter2Size+= dstFilter->length - 1; | |
81b7c056 | 1109 | ASSERT(filter2Size>0) |
8dfe9094 | 1110 | filter2= av_malloc(filter2Size*dstW*sizeof(double)); |
c7f822d9 MN |
1111 | |
1112 | for(i=0; i<dstW; i++) | |
1113 | { | |
1114 | int j; | |
1115 | SwsVector scaleFilter; | |
1116 | SwsVector *outVec; | |
1117 | ||
1118 | scaleFilter.coeff= filter + i*filterSize; | |
1119 | scaleFilter.length= filterSize; | |
1120 | ||
d4e24275 | 1121 | if(srcFilter) outVec= sws_getConvVec(srcFilter, &scaleFilter); |
c7f822d9 MN |
1122 | else outVec= &scaleFilter; |
1123 | ||
1124 | ASSERT(outVec->length == filter2Size) | |
1125 | //FIXME dstFilter | |
1126 | ||
1127 | for(j=0; j<outVec->length; j++) | |
1128 | { | |
1129 | filter2[i*filter2Size + j]= outVec->coeff[j]; | |
1130 | } | |
1131 | ||
1132 | (*filterPos)[i]+= (filterSize-1)/2 - (filter2Size-1)/2; | |
1133 | ||
d4e24275 | 1134 | if(outVec != &scaleFilter) sws_freeVec(outVec); |
c7f822d9 | 1135 | } |
94c4def2 | 1136 | av_free(filter); filter=NULL; |
c7f822d9 MN |
1137 | |
1138 | /* try to reduce the filter-size (step1 find size and shift left) */ | |
1139 | // Assume its near normalized (*0.5 or *2.0 is ok but * 0.001 is not) | |
1140 | minFilterSize= 0; | |
1141 | for(i=dstW-1; i>=0; i--) | |
1142 | { | |
1143 | int min= filter2Size; | |
1144 | int j; | |
1145 | double cutOff=0.0; | |
1146 | ||
1147 | /* get rid off near zero elements on the left by shifting left */ | |
1148 | for(j=0; j<filter2Size; j++) | |
1149 | { | |
1150 | int k; | |
05749630 | 1151 | cutOff += FFABS(filter2[i*filter2Size]); |
c7f822d9 MN |
1152 | |
1153 | if(cutOff > SWS_MAX_REDUCE_CUTOFF) break; | |
1154 | ||
77a416e8 | 1155 | /* preserve Monotonicity because the core can't handle the filter otherwise */ |
c7f822d9 MN |
1156 | if(i<dstW-1 && (*filterPos)[i] >= (*filterPos)[i+1]) break; |
1157 | ||
1158 | // Move filter coeffs left | |
1159 | for(k=1; k<filter2Size; k++) | |
1160 | filter2[i*filter2Size + k - 1]= filter2[i*filter2Size + k]; | |
1161 | filter2[i*filter2Size + k - 1]= 0.0; | |
1162 | (*filterPos)[i]++; | |
1163 | } | |
1164 | ||
1165 | cutOff=0.0; | |
1166 | /* count near zeros on the right */ | |
1167 | for(j=filter2Size-1; j>0; j--) | |
1168 | { | |
05749630 | 1169 | cutOff += FFABS(filter2[i*filter2Size + j]); |
c7f822d9 MN |
1170 | |
1171 | if(cutOff > SWS_MAX_REDUCE_CUTOFF) break; | |
1172 | min--; | |
1173 | } | |
1174 | ||
1175 | if(min>minFilterSize) minFilterSize= min; | |
1176 | } | |
1177 | ||
8c266f0c RD |
1178 | if (flags & SWS_CPU_CAPS_ALTIVEC) { |
1179 | // we can handle the special case 4, | |
1180 | // so we don't want to go to the full 8 | |
1181 | if (minFilterSize < 5) | |
1182 | filterAlign = 4; | |
1183 | ||
1184 | // we really don't want to waste our time | |
1185 | // doing useless computation, so fall-back on | |
1186 | // the scalar C code for very small filter. | |
1187 | // vectorizing is worth it only if you have | |
1188 | // decent-sized vector. | |
1189 | if (minFilterSize < 3) | |
1190 | filterAlign = 1; | |
1191 | } | |
1192 | ||
bca11e75 MN |
1193 | if (flags & SWS_CPU_CAPS_MMX) { |
1194 | // special case for unscaled vertical filtering | |
1195 | if(minFilterSize == 1 && filterAlign == 2) | |
1196 | filterAlign= 1; | |
1197 | } | |
1198 | ||
81b7c056 | 1199 | ASSERT(minFilterSize > 0) |
6c7506de | 1200 | filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1)); |
81b7c056 | 1201 | ASSERT(filterSize > 0) |
8dfe9094 | 1202 | filter= av_malloc(filterSize*dstW*sizeof(double)); |
bca11e75 MN |
1203 | if(filterSize >= MAX_FILTER_SIZE) |
1204 | return -1; | |
6c7506de MN |
1205 | *outFilterSize= filterSize; |
1206 | ||
4a53a912 | 1207 | if(flags&SWS_PRINT_INFO) |
2d529db5 | 1208 | av_log(NULL, AV_LOG_VERBOSE, "SwScaler: reducing / aligning filtersize %d -> %d\n", filter2Size, filterSize); |
c7f822d9 MN |
1209 | /* try to reduce the filter-size (step2 reduce it) */ |
1210 | for(i=0; i<dstW; i++) | |
1211 | { | |
1212 | int j; | |
1213 | ||
6c7506de MN |
1214 | for(j=0; j<filterSize; j++) |
1215 | { | |
1216 | if(j>=filter2Size) filter[i*filterSize + j]= 0.0; | |
1217 | else filter[i*filterSize + j]= filter2[i*filter2Size + j]; | |
1218 | } | |
c7f822d9 | 1219 | } |
94c4def2 | 1220 | av_free(filter2); filter2=NULL; |
6a4970ab | 1221 | |
c7f822d9 MN |
1222 | |
1223 | //FIXME try to align filterpos if possible | |
1224 | ||
28bf81c9 MN |
1225 | //fix borders |
1226 | for(i=0; i<dstW; i++) | |
1227 | { | |
1228 | int j; | |
c7f822d9 | 1229 | if((*filterPos)[i] < 0) |
28bf81c9 MN |
1230 | { |
1231 | // Move filter coeffs left to compensate for filterPos | |
6c7506de | 1232 | for(j=1; j<filterSize; j++) |
28bf81c9 | 1233 | { |
6f209cb5 | 1234 | int left= FFMAX(j + (*filterPos)[i], 0); |
6c7506de MN |
1235 | filter[i*filterSize + left] += filter[i*filterSize + j]; |
1236 | filter[i*filterSize + j]=0; | |
28bf81c9 | 1237 | } |
c7f822d9 | 1238 | (*filterPos)[i]= 0; |
28bf81c9 MN |
1239 | } |
1240 | ||
6c7506de | 1241 | if((*filterPos)[i] + filterSize > srcW) |
28bf81c9 | 1242 | { |
6c7506de | 1243 | int shift= (*filterPos)[i] + filterSize - srcW; |
28bf81c9 | 1244 | // Move filter coeffs right to compensate for filterPos |
6c7506de | 1245 | for(j=filterSize-2; j>=0; j--) |
28bf81c9 | 1246 | { |
6f209cb5 | 1247 | int right= FFMIN(j + shift, filterSize-1); |
6c7506de MN |
1248 | filter[i*filterSize +right] += filter[i*filterSize +j]; |
1249 | filter[i*filterSize +j]=0; | |
28bf81c9 | 1250 | } |
6c7506de | 1251 | (*filterPos)[i]= srcW - filterSize; |
28bf81c9 MN |
1252 | } |
1253 | } | |
1254 | ||
6c7506de | 1255 | // Note the +1 is for the MMXscaler which reads over the end |
5edb653b | 1256 | /* align at 16 for AltiVec (needed by hScale_altivec_real) */ |
0dea6433 | 1257 | *outFilter= av_mallocz(*outFilterSize*(dstW+1)*sizeof(int16_t)); |
c7f822d9 MN |
1258 | |
1259 | /* Normalize & Store in outFilter */ | |
28bf81c9 MN |
1260 | for(i=0; i<dstW; i++) |
1261 | { | |
1262 | int j; | |
ff490720 | 1263 | double error=0; |
28bf81c9 MN |
1264 | double sum=0; |
1265 | double scale= one; | |
ff490720 | 1266 | |
6c7506de | 1267 | for(j=0; j<filterSize; j++) |
28bf81c9 | 1268 | { |
6c7506de | 1269 | sum+= filter[i*filterSize + j]; |
28bf81c9 MN |
1270 | } |
1271 | scale/= sum; | |
93768378 | 1272 | for(j=0; j<*outFilterSize; j++) |
28bf81c9 | 1273 | { |
ff490720 MN |
1274 | double v= filter[i*filterSize + j]*scale + error; |
1275 | int intV= floor(v + 0.5); | |
1276 | (*outFilter)[i*(*outFilterSize) + j]= intV; | |
1277 | error = v - intV; | |
28bf81c9 MN |
1278 | } |
1279 | } | |
6a4970ab | 1280 | |
adeaecb9 MN |
1281 | (*filterPos)[dstW]= (*filterPos)[dstW-1]; // the MMX scaler will read over the end |
1282 | for(i=0; i<*outFilterSize; i++) | |
1283 | { | |
1284 | int j= dstW*(*outFilterSize); | |
1285 | (*outFilter)[j + i]= (*outFilter)[j + i - (*outFilterSize)]; | |
1286 | } | |
c7f822d9 | 1287 | |
94c4def2 | 1288 | av_free(filter); |
bca11e75 | 1289 | return 0; |
7630f2e0 | 1290 | } |
31190492 | 1291 | |
17c613ef | 1292 | #ifdef COMPILE_MMX2 |
b7dc6f66 | 1293 | static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *filter, int32_t *filterPos, int numSplits) |
28bf81c9 | 1294 | { |
b7dc6f66 | 1295 | uint8_t *fragmentA; |
6e1c66bc AJ |
1296 | long imm8OfPShufW1A; |
1297 | long imm8OfPShufW2A; | |
1298 | long fragmentLengthA; | |
b7dc6f66 | 1299 | uint8_t *fragmentB; |
6e1c66bc AJ |
1300 | long imm8OfPShufW1B; |
1301 | long imm8OfPShufW2B; | |
1302 | long fragmentLengthB; | |
b7dc6f66 | 1303 | int fragmentPos; |
28bf81c9 MN |
1304 | |
1305 | int xpos, i; | |
1306 | ||
1307 | // create an optimized horizontal scaling routine | |
1308 | ||
1309 | //code fragment | |
1310 | ||
1311 | asm volatile( | |
1312 | "jmp 9f \n\t" | |
1313 | // Begin | |
1314 | "0: \n\t" | |
6a4970ab DB |
1315 | "movq (%%"REG_d", %%"REG_a"), %%mm3\n\t" |
1316 | "movd (%%"REG_c", %%"REG_S"), %%mm0\n\t" | |
6e1c66bc | 1317 | "movd 1(%%"REG_c", %%"REG_S"), %%mm1\n\t" |
b7dc6f66 MN |
1318 | "punpcklbw %%mm7, %%mm1 \n\t" |
1319 | "punpcklbw %%mm7, %%mm0 \n\t" | |
28bf81c9 MN |
1320 | "pshufw $0xFF, %%mm1, %%mm1 \n\t" |
1321 | "1: \n\t" | |
28bf81c9 MN |
1322 | "pshufw $0xFF, %%mm0, %%mm0 \n\t" |
1323 | "2: \n\t" | |
28bf81c9 | 1324 | "psubw %%mm1, %%mm0 \n\t" |
6d606c4f | 1325 | "movl 8(%%"REG_b", %%"REG_a"), %%esi\n\t" |
28bf81c9 | 1326 | "pmullw %%mm3, %%mm0 \n\t" |
28bf81c9 MN |
1327 | "psllw $7, %%mm1 \n\t" |
1328 | "paddw %%mm1, %%mm0 \n\t" | |
1329 | ||
6e1c66bc | 1330 | "movq %%mm0, (%%"REG_D", %%"REG_a")\n\t" |
28bf81c9 | 1331 | |
6e1c66bc | 1332 | "add $8, %%"REG_a" \n\t" |
28bf81c9 MN |
1333 | // End |
1334 | "9: \n\t" | |
1335 | // "int $3\n\t" | |
6e1c66bc AJ |
1336 | "lea 0b, %0 \n\t" |
1337 | "lea 1b, %1 \n\t" | |
1338 | "lea 2b, %2 \n\t" | |
1339 | "dec %1 \n\t" | |
1340 | "dec %2 \n\t" | |
1341 | "sub %0, %1 \n\t" | |
1342 | "sub %0, %2 \n\t" | |
1343 | "lea 9b, %3 \n\t" | |
1344 | "sub %0, %3 \n\t" | |
b7dc6f66 MN |
1345 | |
1346 | ||
1347 | :"=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A), | |
1348 | "=r" (fragmentLengthA) | |
28bf81c9 MN |
1349 | ); |
1350 | ||
b7dc6f66 MN |
1351 | asm volatile( |
1352 | "jmp 9f \n\t" | |
1353 | // Begin | |
1354 | "0: \n\t" | |
6a4970ab DB |
1355 | "movq (%%"REG_d", %%"REG_a"), %%mm3\n\t" |
1356 | "movd (%%"REG_c", %%"REG_S"), %%mm0\n\t" | |
b7dc6f66 MN |
1357 | "punpcklbw %%mm7, %%mm0 \n\t" |
1358 | "pshufw $0xFF, %%mm0, %%mm1 \n\t" | |
1359 | "1: \n\t" | |
1360 | "pshufw $0xFF, %%mm0, %%mm0 \n\t" | |
1361 | "2: \n\t" | |
1362 | "psubw %%mm1, %%mm0 \n\t" | |
6d606c4f | 1363 | "movl 8(%%"REG_b", %%"REG_a"), %%esi\n\t" |
b7dc6f66 MN |
1364 | "pmullw %%mm3, %%mm0 \n\t" |
1365 | "psllw $7, %%mm1 \n\t" | |
1366 | "paddw %%mm1, %%mm0 \n\t" | |
1367 | ||
6e1c66bc | 1368 | "movq %%mm0, (%%"REG_D", %%"REG_a")\n\t" |
28bf81c9 | 1369 | |
6e1c66bc | 1370 | "add $8, %%"REG_a" \n\t" |
b7dc6f66 MN |
1371 | // End |
1372 | "9: \n\t" | |
1373 | // "int $3\n\t" | |
6e1c66bc AJ |
1374 | "lea 0b, %0 \n\t" |
1375 | "lea 1b, %1 \n\t" | |
1376 | "lea 2b, %2 \n\t" | |
1377 | "dec %1 \n\t" | |
1378 | "dec %2 \n\t" | |
1379 | "sub %0, %1 \n\t" | |
1380 | "sub %0, %2 \n\t" | |
1381 | "lea 9b, %3 \n\t" | |
1382 | "sub %0, %3 \n\t" | |
b7dc6f66 MN |
1383 | |
1384 | ||
1385 | :"=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B), | |
1386 | "=r" (fragmentLengthB) | |
1387 | ); | |
1388 | ||
1389 | xpos= 0; //lumXInc/2 - 0x8000; // difference between pixel centers | |
1390 | fragmentPos=0; | |
6a4970ab | 1391 | |
b7dc6f66 | 1392 | for(i=0; i<dstW/numSplits; i++) |
28bf81c9 MN |
1393 | { |
1394 | int xx=xpos>>16; | |
1395 | ||
1396 | if((i&3) == 0) | |
1397 | { | |
1398 | int a=0; | |
1399 | int b=((xpos+xInc)>>16) - xx; | |
1400 | int c=((xpos+xInc*2)>>16) - xx; | |
1401 | int d=((xpos+xInc*3)>>16) - xx; | |
1402 | ||
b7dc6f66 MN |
1403 | filter[i ] = (( xpos & 0xFFFF) ^ 0xFFFF)>>9; |
1404 | filter[i+1] = (((xpos+xInc ) & 0xFFFF) ^ 0xFFFF)>>9; | |
1405 | filter[i+2] = (((xpos+xInc*2) & 0xFFFF) ^ 0xFFFF)>>9; | |
1406 | filter[i+3] = (((xpos+xInc*3) & 0xFFFF) ^ 0xFFFF)>>9; | |
1407 | filterPos[i/2]= xx; | |
1408 | ||
1409 | if(d+1<4) | |
1410 | { | |
1411 | int maxShift= 3-(d+1); | |
1412 | int shift=0; | |
1413 | ||
1414 | memcpy(funnyCode + fragmentPos, fragmentB, fragmentLengthB); | |
1415 | ||
1416 | funnyCode[fragmentPos + imm8OfPShufW1B]= | |
1417 | (a+1) | ((b+1)<<2) | ((c+1)<<4) | ((d+1)<<6); | |
1418 | funnyCode[fragmentPos + imm8OfPShufW2B]= | |
1419 | a | (b<<2) | (c<<4) | (d<<6); | |
1420 | ||
1421 | if(i+3>=dstW) shift=maxShift; //avoid overread | |
1422 | else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //Align | |
1423 | ||
1424 | if(shift && i>=shift) | |
1425 | { | |
1426 | funnyCode[fragmentPos + imm8OfPShufW1B]+= 0x55*shift; | |
1427 | funnyCode[fragmentPos + imm8OfPShufW2B]+= 0x55*shift; | |
1428 | filterPos[i/2]-=shift; | |
1429 | } | |
1430 | ||
1431 | fragmentPos+= fragmentLengthB; | |
1432 | } | |
1433 | else | |
1434 | { | |
1435 | int maxShift= 3-d; | |
1436 | int shift=0; | |
1437 | ||
1438 | memcpy(funnyCode + fragmentPos, fragmentA, fragmentLengthA); | |
28bf81c9 | 1439 | |
b7dc6f66 MN |
1440 | funnyCode[fragmentPos + imm8OfPShufW1A]= |
1441 | funnyCode[fragmentPos + imm8OfPShufW2A]= | |
1442 | a | (b<<2) | (c<<4) | (d<<6); | |
28bf81c9 | 1443 | |
b7dc6f66 MN |
1444 | if(i+4>=dstW) shift=maxShift; //avoid overread |
1445 | else if((filterPos[i/2]&3) <= maxShift) shift=filterPos[i/2]&3; //partial align | |
28bf81c9 | 1446 | |
b7dc6f66 MN |
1447 | if(shift && i>=shift) |
1448 | { | |
1449 | funnyCode[fragmentPos + imm8OfPShufW1A]+= 0x55*shift; | |
1450 | funnyCode[fragmentPos + imm8OfPShufW2A]+= 0x55*shift; | |
1451 | filterPos[i/2]-=shift; | |
1452 | } | |
1453 | ||
1454 | fragmentPos+= fragmentLengthA; | |
1455 | } | |
1456 | ||
1457 | funnyCode[fragmentPos]= RET; | |
28bf81c9 MN |
1458 | } |
1459 | xpos+=xInc; | |
1460 | } | |
b7dc6f66 | 1461 | filterPos[i/2]= xpos>>16; // needed to jump to the next part |
28bf81c9 | 1462 | } |
17c613ef | 1463 | #endif /* COMPILE_MMX2 */ |
28bf81c9 | 1464 | |
9b2283cc | 1465 | static void globalInit(void){ |
31190492 A |
1466 | // generating tables: |
1467 | int i; | |
c1b0bfb4 | 1468 | for(i=0; i<768; i++){ |
adcec46a | 1469 | int c= av_clip_uint8(i-256); |
c1b0bfb4 | 1470 | clip_table[i]=c; |
b18ea156 | 1471 | } |
516b1f82 | 1472 | } |
c1b0bfb4 | 1473 | |
516b1f82 | 1474 | static SwsFunc getSwsFunc(int flags){ |
6a4970ab | 1475 | |
9bde778e | 1476 | #if defined(RUNTIME_CPUDETECT) && defined (CONFIG_GPL) |
3d6a30d9 | 1477 | #if defined(ARCH_X86) |
28bf81c9 | 1478 | // ordered per speed fasterst first |
516b1f82 MN |
1479 | if(flags & SWS_CPU_CAPS_MMX2) |
1480 | return swScale_MMX2; | |
1481 | else if(flags & SWS_CPU_CAPS_3DNOW) | |
1482 | return swScale_3DNow; | |
1483 | else if(flags & SWS_CPU_CAPS_MMX) | |
1484 | return swScale_MMX; | |
28bf81c9 | 1485 | else |
516b1f82 | 1486 | return swScale_C; |
28bf81c9 MN |
1487 | |
1488 | #else | |
a2faa401 RD |
1489 | #ifdef ARCH_POWERPC |
1490 | if(flags & SWS_CPU_CAPS_ALTIVEC) | |
1491 | return swScale_altivec; | |
1492 | else | |
1493 | return swScale_C; | |
1494 | #endif | |
516b1f82 | 1495 | return swScale_C; |
3d6a30d9 | 1496 | #endif /* defined(ARCH_X86) */ |
28bf81c9 MN |
1497 | #else //RUNTIME_CPUDETECT |
1498 | #ifdef HAVE_MMX2 | |
516b1f82 | 1499 | return swScale_MMX2; |
28bf81c9 | 1500 | #elif defined (HAVE_3DNOW) |
516b1f82 | 1501 | return swScale_3DNow; |
28bf81c9 | 1502 | #elif defined (HAVE_MMX) |
516b1f82 | 1503 | return swScale_MMX; |
a2faa401 RD |
1504 | #elif defined (HAVE_ALTIVEC) |
1505 | return swScale_altivec; | |
28bf81c9 | 1506 | #else |
516b1f82 | 1507 | return swScale_C; |
28bf81c9 MN |
1508 | #endif |
1509 | #endif //!RUNTIME_CPUDETECT | |
31190492 | 1510 | } |
7630f2e0 | 1511 | |
d4e24275 | 1512 | static int PlanarToNV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
0d9f3d85 A |
1513 | int srcSliceH, uint8_t* dstParam[], int dstStride[]){ |
1514 | uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; | |
1515 | /* Copy Y plane */ | |
12e11662 | 1516 | if(dstStride[0]==srcStride[0] && srcStride[0] > 0) |
0d9f3d85 A |
1517 | memcpy(dst, src[0], srcSliceH*dstStride[0]); |
1518 | else | |
1519 | { | |
1520 | int i; | |
1521 | uint8_t *srcPtr= src[0]; | |
1522 | uint8_t *dstPtr= dst; | |
1523 | for(i=0; i<srcSliceH; i++) | |
1524 | { | |
6118e52e | 1525 | memcpy(dstPtr, srcPtr, c->srcW); |
0d9f3d85 A |
1526 | srcPtr+= srcStride[0]; |
1527 | dstPtr+= dstStride[0]; | |
1528 | } | |
1529 | } | |
6118e52e | 1530 | dst = dstParam[1] + dstStride[1]*srcSliceY/2; |
e9e12f0e | 1531 | if (c->dstFormat == PIX_FMT_NV12) |
6118e52e VS |
1532 | interleaveBytes( src[1],src[2],dst,c->srcW/2,srcSliceH/2,srcStride[1],srcStride[2],dstStride[0] ); |
1533 | else | |
1534 | interleaveBytes( src[2],src[1],dst,c->srcW/2,srcSliceH/2,srcStride[2],srcStride[1],dstStride[0] ); | |
fccb9b2b | 1535 | |
d4e24275 | 1536 | return srcSliceH; |
0d9f3d85 A |
1537 | } |
1538 | ||
d4e24275 | 1539 | static int PlanarToYuy2Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
0d9f3d85 A |
1540 | int srcSliceH, uint8_t* dstParam[], int dstStride[]){ |
1541 | uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; | |
1542 | ||
fccb9b2b MN |
1543 | yv12toyuy2( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] ); |
1544 | ||
d4e24275 | 1545 | return srcSliceH; |
0d9f3d85 A |
1546 | } |
1547 | ||
caeaabe7 AB |
1548 | static int PlanarToUyvyWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
1549 | int srcSliceH, uint8_t* dstParam[], int dstStride[]){ | |
1550 | uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY; | |
1551 | ||
1552 | yv12touyvy( src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0] ); | |
1553 | ||
1554 | return srcSliceH; | |
1555 | } | |
1556 | ||
e09d12f4 | 1557 | /* {RGB,BGR}{15,16,24,32} -> {RGB,BGR}{15,16,24,32} */ |
d4e24275 | 1558 | static int rgb2rgbWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
e09d12f4 MN |
1559 | int srcSliceH, uint8_t* dst[], int dstStride[]){ |
1560 | const int srcFormat= c->srcFormat; | |
1561 | const int dstFormat= c->dstFormat; | |
e9e12f0e LA |
1562 | const int srcBpp= (fmt_depth(srcFormat) + 7) >> 3; |
1563 | const int dstBpp= (fmt_depth(dstFormat) + 7) >> 3; | |
1564 | const int srcId= fmt_depth(srcFormat) >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */ | |
1565 | const int dstId= fmt_depth(dstFormat) >> 2; | |
73cbfb1c | 1566 | void (*conv)(const uint8_t *src, uint8_t *dst, long src_size)=NULL; |
e09d12f4 MN |
1567 | |
1568 | /* BGR -> BGR */ | |
20380eb8 MN |
1569 | if( (isBGR(srcFormat) && isBGR(dstFormat)) |
1570 | || (isRGB(srcFormat) && isRGB(dstFormat))){ | |
e09d12f4 MN |
1571 | switch(srcId | (dstId<<4)){ |
1572 | case 0x34: conv= rgb16to15; break; | |
1573 | case 0x36: conv= rgb24to15; break; | |
1574 | case 0x38: conv= rgb32to15; break; | |
1575 | case 0x43: conv= rgb15to16; break; | |
1576 | case 0x46: conv= rgb24to16; break; | |
1577 | case 0x48: conv= rgb32to16; break; | |
1578 | case 0x63: conv= rgb15to24; break; | |
1579 | case 0x64: conv= rgb16to24; break; | |
1580 | case 0x68: conv= rgb32to24; break; | |
1581 | case 0x83: conv= rgb15to32; break; | |
1582 | case 0x84: conv= rgb16to32; break; | |
1583 | case 0x86: conv= rgb24to32; break; | |
6a4970ab | 1584 | default: av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n", |
94c4def2 | 1585 | sws_format_name(srcFormat), sws_format_name(dstFormat)); break; |
b935781b | 1586 | } |
20380eb8 MN |
1587 | }else if( (isBGR(srcFormat) && isRGB(dstFormat)) |
1588 | || (isRGB(srcFormat) && isBGR(dstFormat))){ | |
e09d12f4 MN |
1589 | switch(srcId | (dstId<<4)){ |
1590 | case 0x33: conv= rgb15tobgr15; break; | |
1591 | case 0x34: conv= rgb16tobgr15; break; | |
1592 | case 0x36: conv= rgb24tobgr15; break; | |
1593 | case 0x38: conv= rgb32tobgr15; break; | |
1594 | case 0x43: conv= rgb15tobgr16; break; | |
1595 | case 0x44: conv= rgb16tobgr16; break; | |
1596 | case 0x46: conv= rgb24tobgr16; break; | |
1597 | case 0x48: conv= rgb32tobgr16; break; | |
1598 | case 0x63: conv= rgb15tobgr24; break; | |
1599 | case 0x64: conv= rgb16tobgr24; break; | |
1600 | case 0x66: conv= rgb24tobgr24; break; | |
1601 | case 0x68: conv= rgb32tobgr24; break; | |
1602 | case 0x83: conv= rgb15tobgr32; break; | |
1603 | case 0x84: conv= rgb16tobgr32; break; | |
1604 | case 0x86: conv= rgb24tobgr32; break; | |
1605 | case 0x88: conv= rgb32tobgr32; break; | |
6a4970ab | 1606 | default: av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n", |
94c4def2 | 1607 | sws_format_name(srcFormat), sws_format_name(dstFormat)); break; |
0d9f3d85 | 1608 | } |
20380eb8 | 1609 | }else{ |
6a4970ab | 1610 | av_log(c, AV_LOG_ERROR, "swScaler: internal error %s -> %s converter\n", |
94c4def2 | 1611 | sws_format_name(srcFormat), sws_format_name(dstFormat)); |
e09d12f4 | 1612 | } |
20380eb8 | 1613 | |
e09d12f4 MN |
1614 | if(dstStride[0]*srcBpp == srcStride[0]*dstBpp) |
1615 | conv(src[0], dst[0] + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); | |
0d9f3d85 A |
1616 | else |
1617 | { | |
1618 | int i; | |
1619 | uint8_t *srcPtr= src[0]; | |
1620 | uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; | |
1621 | ||
1622 | for(i=0; i<srcSliceH; i++) | |
1623 | { | |
e09d12f4 | 1624 | conv(srcPtr, dstPtr, c->srcW*srcBpp); |
0d9f3d85 A |
1625 | srcPtr+= srcStride[0]; |
1626 | dstPtr+= dstStride[0]; | |
1627 | } | |
6a4970ab | 1628 | } |
d4e24275 | 1629 | return srcSliceH; |
0d9f3d85 A |
1630 | } |
1631 | ||
d4e24275 | 1632 | static int bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
ec22603f MN |
1633 | int srcSliceH, uint8_t* dst[], int dstStride[]){ |
1634 | ||
1635 | rgb24toyv12( | |
6a4970ab DB |
1636 | src[0], |
1637 | dst[0]+ srcSliceY *dstStride[0], | |
1638 | dst[1]+(srcSliceY>>1)*dstStride[1], | |
ec22603f | 1639 | dst[2]+(srcSliceY>>1)*dstStride[2], |
6a4970ab | 1640 | c->srcW, srcSliceH, |
ec22603f | 1641 | dstStride[0], dstStride[1], srcStride[0]); |
d4e24275 | 1642 | return srcSliceH; |
ec22603f MN |
1643 | } |
1644 | ||
d4e24275 | 1645 | static int yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
b241cbf2 MN |
1646 | int srcSliceH, uint8_t* dst[], int dstStride[]){ |
1647 | int i; | |
1648 | ||
1649 | /* copy Y */ | |
6a4970ab | 1650 | if(srcStride[0]==dstStride[0] && srcStride[0] > 0) |
b241cbf2 MN |
1651 | memcpy(dst[0]+ srcSliceY*dstStride[0], src[0], srcStride[0]*srcSliceH); |
1652 | else{ | |
1653 | uint8_t *srcPtr= src[0]; | |
1654 | uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; | |
1655 | ||
1656 | for(i=0; i<srcSliceH; i++) | |
1657 | { | |
1658 | memcpy(dstPtr, srcPtr, c->srcW); | |
1659 | srcPtr+= srcStride[0]; | |
1660 | dstPtr+= dstStride[0]; | |
1661 | } | |
1662 | } | |
1663 | ||
e9e12f0e | 1664 | if(c->dstFormat==PIX_FMT_YUV420P){ |
b241cbf2 MN |
1665 | planar2x(src[1], dst[1], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[1]); |
1666 | planar2x(src[2], dst[2], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[2]); | |
1667 | }else{ | |
1668 | planar2x(src[1], dst[2], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[2]); | |
1669 | planar2x(src[2], dst[1], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[1]); | |
1670 | } | |
d4e24275 | 1671 | return srcSliceH; |
b241cbf2 MN |
1672 | } |
1673 | ||
b6654a54 | 1674 | /* unscaled copy like stuff (assumes nearly identical formats) */ |
3e499f53 MN |
1675 | static int simpleCopy(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
1676 | int srcSliceH, uint8_t* dst[], int dstStride[]){ | |
b6654a54 MN |
1677 | |
1678 | if(isPacked(c->srcFormat)) | |
1679 | { | |
12e11662 | 1680 | if(dstStride[0]==srcStride[0] && srcStride[0] > 0) |
b6654a54 MN |
1681 | memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]); |
1682 | else | |
1683 | { | |
1684 | int i; | |
1685 | uint8_t *srcPtr= src[0]; | |
1686 | uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY; | |
a861d4d7 MN |
1687 | int length=0; |
1688 | ||
1689 | /* universal length finder */ | |
6a4970ab | 1690 | while(length+c->srcW <= FFABS(dstStride[0]) |
05749630 | 1691 | && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW; |
a861d4d7 | 1692 | ASSERT(length!=0); |
b6654a54 MN |
1693 | |
1694 | for(i=0; i<srcSliceH; i++) | |
1695 | { | |
1696 | memcpy(dstPtr, srcPtr, length); | |
1697 | srcPtr+= srcStride[0]; | |
1698 | dstPtr+= dstStride[0]; | |
1699 | } | |
1700 | } | |
1701 | } | |
6a4970ab | 1702 | else |
44c1035c | 1703 | { /* Planar YUV or gray */ |
b6654a54 MN |
1704 | int plane; |
1705 | for(plane=0; plane<3; plane++) | |
1706 | { | |
e616aa93 MN |
1707 | int length= plane==0 ? c->srcW : -((-c->srcW )>>c->chrDstHSubSample); |
1708 | int y= plane==0 ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample); | |
1709 | int height= plane==0 ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample); | |
44c1035c MN |
1710 | |
1711 | if((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0) | |
0d9f3d85 | 1712 | { |
44c1035c | 1713 | if(!isGray(c->dstFormat)) |
e616aa93 | 1714 | memset(dst[plane], 128, dstStride[plane]*height); |
0d9f3d85 | 1715 | } |
b6654a54 MN |
1716 | else |
1717 | { | |
12e11662 | 1718 | if(dstStride[plane]==srcStride[plane] && srcStride[plane] > 0) |
44c1035c MN |
1719 | memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]); |
1720 | else | |
b6654a54 | 1721 | { |
44c1035c MN |
1722 | int i; |
1723 | uint8_t *srcPtr= src[plane]; | |
1724 | uint8_t *dstPtr= dst[plane] + dstStride[plane]*y; | |
1725 | for(i=0; i<height; i++) | |
1726 | { | |
1727 | memcpy(dstPtr, srcPtr, length); | |
1728 | srcPtr+= srcStride[plane]; | |
1729 | dstPtr+= dstStride[plane]; | |
1730 | } | |
b6654a54 MN |
1731 | } |
1732 | } | |
1733 | } | |
1734 | } | |
d4e24275 | 1735 | return srcSliceH; |
37079906 | 1736 | } |
28bf81c9 | 1737 | |
4884b9e5 KS |
1738 | static int gray16togray(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
1739 | int srcSliceH, uint8_t* dst[], int dstStride[]){ | |
1740 | ||
1741 | int length= c->srcW; | |
1742 | int y= srcSliceY; | |
1743 | int height= srcSliceH; | |
1744 | int i, j; | |
1745 | uint8_t *srcPtr= src[0]; | |
1746 | uint8_t *dstPtr= dst[0] + dstStride[0]*y; | |
1747 | ||
1748 | if(!isGray(c->dstFormat)){ | |
1749 | int height= -((-srcSliceH)>>c->chrDstVSubSample); | |
1750 | memset(dst[1], 128, dstStride[1]*height); | |
1751 | memset(dst[2], 128, dstStride[2]*height); | |
1752 | } | |
1753 | if(c->srcFormat == PIX_FMT_GRAY16LE) srcPtr++; | |
1754 | for(i=0; i<height; i++) | |
1755 | { | |
1756 | for(j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1]; | |
1757 | srcPtr+= srcStride[0]; | |
1758 | dstPtr+= dstStride[0]; | |
1759 | } | |
1760 | return srcSliceH; | |
1761 | } | |
1762 | ||
1763 | static int graytogray16(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, | |
1764 | int srcSliceH, uint8_t* dst[], int dstStride[]){ | |
1765 | ||
1766 | int length= c->srcW; | |
1767 | int y= srcSliceY; | |
1768 | int height= srcSliceH; | |
1769 | int i, j; | |
1770 | uint8_t *srcPtr= src[0]; | |
1771 | uint8_t *dstPtr= dst[0] + dstStride[0]*y; | |
1772 | for(i=0; i<height; i++) | |
1773 | { | |
1774 | for(j=0; j<length; j++) | |
1775 | { | |
1776 | dstPtr[j<<1] = srcPtr[j]; | |
1777 | dstPtr[(j<<1)+1] = srcPtr[j]; | |
1778 | } | |
1779 | srcPtr+= srcStride[0]; | |
1780 | dstPtr+= dstStride[0]; | |
1781 | } | |
1782 | return srcSliceH; | |
1783 | } | |
1784 | ||
1785 | static int gray16swap(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, | |
1786 | int srcSliceH, uint8_t* dst[], int dstStride[]){ | |
1787 | ||
1788 | int length= c->srcW; | |
1789 | int y= srcSliceY; | |
1790 | int height= srcSliceH; | |
1791 | int i, j; | |
1792 | uint16_t *srcPtr= src[0]; | |
1793 | uint16_t *dstPtr= dst[0] + dstStride[0]*y/2; | |
1794 | for(i=0; i<height; i++) | |
1795 | { | |
1796 | for(j=0; j<length; j++) dstPtr[j] = bswap_16(srcPtr[j]); | |
1797 | srcPtr+= srcStride[0]/2; | |
1798 | dstPtr+= dstStride[0]/2; | |
1799 | } | |
1800 | return srcSliceH; | |
1801 | } | |
1802 | ||
1803 | ||
c7a810cc MN |
1804 | static void getSubSampleFactors(int *h, int *v, int format){ |
1805 | switch(format){ | |
e9e12f0e LA |
1806 | case PIX_FMT_UYVY422: |
1807 | case PIX_FMT_YUYV422: | |
c7a810cc MN |
1808 | *h=1; |
1809 | *v=0; | |
1810 | break; | |
e9e12f0e | 1811 | case PIX_FMT_YUV420P: |
4884b9e5 KS |
1812 | case PIX_FMT_GRAY16BE: |
1813 | case PIX_FMT_GRAY16LE: | |
e9e12f0e LA |
1814 | case PIX_FMT_GRAY8: //FIXME remove after different subsamplings are fully implemented |
1815 | case PIX_FMT_NV12: | |
1816 | case PIX_FMT_NV21: | |
c7a810cc MN |
1817 | *h=1; |
1818 | *v=1; | |
1819 | break; | |
e9e12f0e | 1820 | case PIX_FMT_YUV410P: |
c7a810cc MN |
1821 | *h=2; |
1822 | *v=2; | |
1823 | break; | |
e9e12f0e | 1824 | case PIX_FMT_YUV444P: |
d80e2fa2 MN |
1825 | *h=0; |
1826 | *v=0; | |
1827 | break; | |
e9e12f0e | 1828 | case PIX_FMT_YUV422P: |
d80e2fa2 MN |
1829 | *h=1; |
1830 | *v=0; | |
1831 | break; | |
e9e12f0e | 1832 | case PIX_FMT_YUV411P: |
d80e2fa2 MN |
1833 | *h=2; |
1834 | *v=0; | |
1835 | break; | |
c7a810cc MN |
1836 | default: |
1837 | *h=0; | |
1838 | *v=0; | |
1839 | break; | |
1840 | } | |
1841 | } | |
1842 | ||
5427e242 MN |
1843 | static uint16_t roundToInt16(int64_t f){ |
1844 | int r= (f + (1<<15))>>16; | |
1845 | if(r<-0x7FFF) return 0x8000; | |
1846 | else if(r> 0x7FFF) return 0x7FFF; | |
1847 | else return r; | |
0481412a MN |
1848 | } |
1849 | ||
1850 | /** | |
5427e242 | 1851 | * @param inv_table the yuv2rgb coeffs, normally Inverse_Table_6_9[x] |
0481412a | 1852 | * @param fullRange if 1 then the luma range is 0..255 if 0 its 16..235 |
5427e242 | 1853 | * @return -1 if not supported |
0481412a | 1854 | */ |
5427e242 MN |
1855 | int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation){ |
1856 | int64_t crv = inv_table[0]; | |
1857 | int64_t cbu = inv_table[1]; | |
1858 | int64_t cgu = -inv_table[2]; | |
1859 | int64_t cgv = -inv_table[3]; | |
1860 | int64_t cy = 1<<16; | |
1861 | int64_t oy = 0; | |
1862 | ||
1863 | if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1; | |
1864 | memcpy(c->srcColorspaceTable, inv_table, sizeof(int)*4); | |
1865 | memcpy(c->dstColorspaceTable, table, sizeof(int)*4); | |
1866 | ||
1867 | c->brightness= brightness; | |
1868 | c->contrast = contrast; | |
1869 | c->saturation= saturation; | |
1870 | c->srcRange = srcRange; | |
1871 | c->dstRange = dstRange; | |
0481412a MN |
1872 | |
1873 | c->uOffset= 0x0400040004000400LL; | |
1874 | c->vOffset= 0x0400040004000400LL; | |
1875 | ||
5427e242 MN |
1876 | if(!srcRange){ |
1877 | cy= (cy*255) / 219; | |
1878 | oy= 16<<16; | |
edf97a75 MN |
1879 | }else{ |
1880 | crv= (crv*224) / 255; | |
1881 | cbu= (cbu*224) / 255; | |
1882 | cgu= (cgu*224) / 255; | |
1883 | cgv= (cgv*224) / 255; | |
1884 | } | |
0481412a | 1885 | |
5427e242 MN |
1886 | cy = (cy *contrast )>>16; |
1887 | crv= (crv*contrast * saturation)>>32; | |
1888 | cbu= (cbu*contrast * saturation)>>32; | |
1889 | cgu= (cgu*contrast * saturation)>>32; | |
1890 | cgv= (cgv*contrast * saturation)>>32; | |
0481412a | 1891 | |
5427e242 | 1892 | oy -= 256*brightness; |
0481412a MN |
1893 | |
1894 | c->yCoeff= roundToInt16(cy *8192) * 0x0001000100010001ULL; | |
1895 | c->vrCoeff= roundToInt16(crv*8192) * 0x0001000100010001ULL; | |
1896 | c->ubCoeff= roundToInt16(cbu*8192) * 0x0001000100010001ULL; | |
1897 | c->vgCoeff= roundToInt16(cgv*8192) * 0x0001000100010001ULL; | |
1898 | c->ugCoeff= roundToInt16(cgu*8192) * 0x0001000100010001ULL; | |
1899 | c->yOffset= roundToInt16(oy * 8) * 0x0001000100010001ULL; | |
5427e242 MN |
1900 | |
1901 | yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation); | |
1902 | //FIXME factorize | |
a31de956 | 1903 | |
6634d0ef NP |
1904 | #ifdef COMPILE_ALTIVEC |
1905 | if (c->flags & SWS_CPU_CAPS_ALTIVEC) | |
1906 | yuv2rgb_altivec_init_tables (c, inv_table, brightness, contrast, saturation); | |
6a4970ab | 1907 | #endif |
5427e242 MN |
1908 | return 0; |
1909 | } | |
1910 | ||
1911 | /** | |
1912 | * @return -1 if not supported | |
1913 | */ | |
1914 | int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation){ | |
1915 | if(isYUV(c->dstFormat) || isGray(c->dstFormat)) return -1; | |
1916 | ||
1917 | *inv_table = c->srcColorspaceTable; | |
1918 | *table = c->dstColorspaceTable; | |
1919 | *srcRange = c->srcRange; | |
1920 | *dstRange = c->dstRange; | |
1921 | *brightness= c->brightness; | |
1922 | *contrast = c->contrast; | |
1923 | *saturation= c->saturation; | |
6a4970ab DB |
1924 | |
1925 | return 0; | |
0481412a MN |
1926 | } |
1927 | ||
44cdb423 LA |
1928 | static int handle_jpeg(int *format) |
1929 | { | |
1930 | switch (*format) { | |
1931 | case PIX_FMT_YUVJ420P: | |
1932 | *format = PIX_FMT_YUV420P; | |
1933 | return 1; | |
1934 | case PIX_FMT_YUVJ422P: | |
1935 | *format = PIX_FMT_YUV422P; | |
1936 | return 1; | |
1937 | case PIX_FMT_YUVJ444P: | |
1938 | *format = PIX_FMT_YUV444P; | |
1939 | return 1; | |
1940 | default: | |
1941 | return 0; | |
1942 | } | |
1943 | } | |
1944 | ||
e9e12f0e | 1945 | SwsContext *sws_getContext(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags, |
66d1cdb6 | 1946 | SwsFilter *srcFilter, SwsFilter *dstFilter, double *param){ |
28bf81c9 | 1947 | |
28bf81c9 MN |
1948 | SwsContext *c; |
1949 | int i; | |
ec62c38f | 1950 | int usesVFilter, usesHFilter; |
e09d12f4 | 1951 | int unscaled, needsDither; |
44cdb423 | 1952 | int srcRange, dstRange; |
c7f822d9 | 1953 | SwsFilter dummyFilter= {NULL, NULL, NULL, NULL}; |
3d6a30d9 | 1954 | #if defined(ARCH_X86) |
516b1f82 | 1955 | if(flags & SWS_CPU_CAPS_MMX) |
5cebb24b MN |
1956 | asm volatile("emms\n\t"::: "memory"); |
1957 | #endif | |
516b1f82 | 1958 | |
9bde778e | 1959 | #if !defined(RUNTIME_CPUDETECT) || !defined (CONFIG_GPL) //ensure that the flags match the compiled variant if cpudetect is off |
a2faa401 | 1960 | flags &= ~(SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2|SWS_CPU_CAPS_3DNOW|SWS_CPU_CAPS_ALTIVEC); |
516b1f82 MN |
1961 | #ifdef HAVE_MMX2 |
1962 | flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_MMX2; | |
1963 | #elif defined (HAVE_3DNOW) | |
1964 | flags |= SWS_CPU_CAPS_MMX|SWS_CPU_CAPS_3DNOW; | |
1965 | #elif defined (HAVE_MMX) | |
1966 | flags |= SWS_CPU_CAPS_MMX; | |
a2faa401 RD |
1967 | #elif defined (HAVE_ALTIVEC) |
1968 | flags |= SWS_CPU_CAPS_ALTIVEC; | |
516b1f82 | 1969 | #endif |
69796008 | 1970 | #endif /* RUNTIME_CPUDETECT */ |
516b1f82 | 1971 | if(clip_table[512] != 255) globalInit(); |
700490a4 | 1972 | if(rgb15to16 == NULL) sws_rgb2rgb_init(flags); |
fccb9b2b | 1973 | |
44c1035c | 1974 | unscaled = (srcW == dstW && srcH == dstH); |
6a4970ab | 1975 | needsDither= (isBGR(dstFormat) || isRGB(dstFormat)) |
e9e12f0e LA |
1976 | && (fmt_depth(dstFormat))<24 |
1977 | && ((fmt_depth(dstFormat))<(fmt_depth(srcFormat)) || (!(isRGB(srcFormat) || isBGR(srcFormat)))); | |
44c1035c | 1978 | |
44cdb423 LA |
1979 | srcRange = handle_jpeg(&srcFormat); |
1980 | dstRange = handle_jpeg(&dstFormat); | |
1981 | ||
6a4970ab | 1982 | if(!isSupportedIn(srcFormat)) |
b81cf274 | 1983 | { |
2d529db5 | 1984 | av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as input format\n", sws_format_name(srcFormat)); |
44c1035c MN |
1985 | return NULL; |
1986 | } | |
1987 | if(!isSupportedOut(dstFormat)) | |
1988 | { | |
2d529db5 | 1989 | av_log(NULL, AV_LOG_ERROR, "swScaler: %s is not supported as output format\n", sws_format_name(dstFormat)); |
44c1035c | 1990 | return NULL; |
b81cf274 | 1991 | } |
44c1035c | 1992 | |
28bf81c9 | 1993 | /* sanity check */ |
b81cf274 MN |
1994 | 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 |
1995 | { | |
6a4970ab | 1996 | av_log(NULL, AV_LOG_ERROR, "swScaler: %dx%d -> %dx%d is invalid scaling dimension\n", |
b81cf274 MN |
1997 | srcW, srcH, dstW, dstH); |
1998 | return NULL; | |
1999 | } | |
28bf81c9 | 2000 | |
c7f822d9 MN |
2001 | if(!dstFilter) dstFilter= &dummyFilter; |
2002 | if(!srcFilter) srcFilter= &dummyFilter; | |
2003 | ||
0dea6433 | 2004 | c= av_mallocz(sizeof(SwsContext)); |
28bf81c9 | 2005 | |
2d529db5 | 2006 | c->av_class = &sws_context_class; |
28bf81c9 MN |
2007 | c->srcW= srcW; |
2008 | c->srcH= srcH; | |
2009 | c->dstW= dstW; | |
2010 | c->dstH= dstH; | |
5521b193 MN |
2011 | c->lumXInc= ((srcW<<16) + (dstW>>1))/dstW; |
2012 | c->lumYInc= ((srcH<<16) + (dstH>>1))/dstH; | |
28bf81c9 MN |
2013 | c->flags= flags; |
2014 | c->dstFormat= dstFormat; | |
2015 | c->srcFormat= srcFormat; | |
379a2036 | 2016 | c->vRounder= 4* 0x0001000100010001ULL; |
28bf81c9 | 2017 | |
ec62c38f MN |
2018 | usesHFilter= usesVFilter= 0; |
2019 | if(dstFilter->lumV!=NULL && dstFilter->lumV->length>1) usesVFilter=1; | |
2020 | if(dstFilter->lumH!=NULL && dstFilter->lumH->length>1) usesHFilter=1; | |
2021 | if(dstFilter->chrV!=NULL && dstFilter->chrV->length>1) usesVFilter=1; | |
2022 | if(dstFilter->chrH!=NULL && dstFilter->chrH->length>1) usesHFilter=1; | |
2023 | if(srcFilter->lumV!=NULL && srcFilter->lumV->length>1) usesVFilter=1; | |
2024 | if(srcFilter->lumH!=NULL && srcFilter->lumH->length>1) usesHFilter=1; | |
2025 | if(srcFilter->chrV!=NULL && srcFilter->chrV->length>1) usesVFilter=1; | |
2026 | if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesHFilter=1; | |
e616aa93 MN |
2027 | |
2028 | getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat); | |
2029 | getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat); | |
2030 | ||
2031 | // reuse chroma for 2 pixles rgb/bgr unless user wants full chroma interpolation | |
2032 | if((isBGR(dstFormat) || isRGB(dstFormat)) && !(flags&SWS_FULL_CHR_H_INT)) c->chrDstHSubSample=1; | |
2033 | ||
5859233b MN |
2034 | // drop some chroma lines if the user wants it |
2035 | c->vChrDrop= (flags&SWS_SRC_V_CHR_DROP_MASK)>>SWS_SRC_V_CHR_DROP_SHIFT; | |
2036 | c->chrSrcVSubSample+= c->vChrDrop; | |
e616aa93 | 2037 | |
5859233b | 2038 | // drop every 2. pixel for chroma calculation unless user wants full chroma |
fa65e2f6 MN |
2039 | if((isBGR(srcFormat) || isRGB(srcFormat)) && !(flags&SWS_FULL_CHR_H_INP) |
2040 | && srcFormat!=PIX_FMT_RGB8 && srcFormat!=PIX_FMT_BGR8 | |
2041 | && srcFormat!=PIX_FMT_RGB4 && srcFormat!=PIX_FMT_BGR4 | |
2042 | && srcFormat!=PIX_FMT_RGB4_BYTE && srcFormat!=PIX_FMT_BGR4_BYTE) | |
e616aa93 MN |
2043 | c->chrSrcHSubSample=1; |
2044 | ||
66d1cdb6 MN |
2045 | if(param){ |
2046 | c->param[0] = param[0]; | |
2047 | c->param[1] = param[1]; | |
2048 | }else{ | |
2049 | c->param[0] = | |
2050 | c->param[1] = SWS_PARAM_DEFAULT; | |
2051 | } | |
2052 | ||
e616aa93 MN |
2053 | c->chrIntHSubSample= c->chrDstHSubSample; |
2054 | c->chrIntVSubSample= c->chrSrcVSubSample; | |
5427e242 | 2055 | |
911406f2 | 2056 | // Note the -((-x)>>y) is so that we always round toward +inf. |
e616aa93 MN |
2057 | c->chrSrcW= -((-srcW) >> c->chrSrcHSubSample); |
2058 | c->chrSrcH= -((-srcH) >> c->chrSrcVSubSample); | |
2059 | c->chrDstW= -((-dstW) >> c->chrDstHSubSample); | |
2060 | c->chrDstH= -((-dstH) >> c->chrDstVSubSample); | |
5427e242 | 2061 | |
6a4970ab | 2062 | sws_setColorspaceDetails(c, Inverse_Table_6_9[SWS_CS_DEFAULT], srcRange, Inverse_Table_6_9[SWS_CS_DEFAULT] /* FIXME*/, dstRange, 0, 1<<16, 1<<16); |
cf7d1c1a | 2063 | |
b935781b | 2064 | /* unscaled special Cases */ |
ec62c38f | 2065 | if(unscaled && !usesHFilter && !usesVFilter) |
37079906 | 2066 | { |
0d9f3d85 | 2067 | /* yv12_to_nv12 */ |
e9e12f0e | 2068 | if(srcFormat == PIX_FMT_YUV420P && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) |
0d9f3d85 A |
2069 | { |
2070 | c->swScale= PlanarToNV12Wrapper; | |
0d9f3d85 | 2071 | } |
9bde778e | 2072 | #ifdef CONFIG_GPL |
37079906 | 2073 | /* yuv2bgr */ |
e9e12f0e | 2074 | if((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P) && (isBGR(dstFormat) || isRGB(dstFormat))) |
37079906 | 2075 | { |
5427e242 | 2076 | c->swScale= yuv2rgb_get_func_ptr(c); |
37079906 | 2077 | } |
9bde778e | 2078 | #endif |
6a4970ab | 2079 | |
e9e12f0e | 2080 | if( srcFormat==PIX_FMT_YUV410P && dstFormat==PIX_FMT_YUV420P ) |
b241cbf2 MN |
2081 | { |
2082 | c->swScale= yvu9toyv12Wrapper; | |
b241cbf2 MN |
2083 | } |
2084 | ||
ec22603f | 2085 | /* bgr24toYV12 */ |
e9e12f0e | 2086 | if(srcFormat==PIX_FMT_BGR24 && dstFormat==PIX_FMT_YUV420P) |
ec22603f | 2087 | c->swScale= bgr24toyv12Wrapper; |
6a4970ab | 2088 | |
e09d12f4 MN |
2089 | /* rgb/bgr -> rgb/bgr (no dither needed forms) */ |
2090 | if( (isBGR(srcFormat) || isRGB(srcFormat)) | |
6a4970ab | 2091 | && (isBGR(dstFormat) || isRGB(dstFormat)) |
94bd08b0 CEH |
2092 | && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8 |
2093 | && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8 | |
2094 | && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4 | |
2095 | && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4 | |
2096 | && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE | |
2097 | && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE | |
2098 | && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK | |
e09d12f4 MN |
2099 | && !needsDither) |
2100 | c->swScale= rgb2rgbWrapper; | |
2101 | ||
2102 | /* LQ converters if -sws 0 or -sws 4*/ | |
2103 | if(c->flags&(SWS_FAST_BILINEAR|SWS_POINT)){ | |
2104 | /* rgb/bgr -> rgb/bgr (dither needed forms) */ | |
2105 | if( (isBGR(srcFormat) || isRGB(srcFormat)) | |
6a4970ab | 2106 | && (isBGR(dstFormat) || isRGB(dstFormat)) |
e09d12f4 MN |
2107 | && needsDither) |
2108 | c->swScale= rgb2rgbWrapper; | |
2ce486d8 MN |
2109 | |
2110 | /* yv12_to_yuy2 */ | |
6a4970ab | 2111 | if(srcFormat == PIX_FMT_YUV420P && |
e9e12f0e | 2112 | (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422)) |
2ce486d8 | 2113 | { |
e9e12f0e | 2114 | if (dstFormat == PIX_FMT_YUYV422) |
caeaabe7 AB |
2115 | c->swScale= PlanarToYuy2Wrapper; |
2116 | else | |
2117 | c->swScale= PlanarToUyvyWrapper; | |
2ce486d8 | 2118 | } |
e09d12f4 | 2119 | } |
ec22603f | 2120 | |
6634d0ef | 2121 | #ifdef COMPILE_ALTIVEC |
b71cf33c | 2122 | if ((c->flags & SWS_CPU_CAPS_ALTIVEC) && |
6a4970ab | 2123 | ((srcFormat == PIX_FMT_YUV420P && |
e9e12f0e | 2124 | (dstFormat == PIX_FMT_YUYV422 || dstFormat == PIX_FMT_UYVY422)))) { |
b71cf33c | 2125 | // unscaled YV12 -> packed YUV, we want speed |
e9e12f0e | 2126 | if (dstFormat == PIX_FMT_YUYV422) |
b71cf33c RD |
2127 | c->swScale= yv12toyuy2_unscaled_altivec; |
2128 | else | |
2129 | c->swScale= yv12touyvy_unscaled_altivec; | |
2130 | } | |
2131 | #endif | |
2132 | ||
20380eb8 MN |
2133 | /* simple copy */ |
2134 | if( srcFormat == dstFormat | |
20380eb8 MN |
2135 | || (isPlanarYUV(srcFormat) && isGray(dstFormat)) |
2136 | || (isPlanarYUV(dstFormat) && isGray(srcFormat)) | |
2137 | ) | |
2138 | { | |
2139 | c->swScale= simpleCopy; | |
2140 | } | |
2141 | ||
4884b9e5 KS |
2142 | /* gray16{le,be} conversions */ |
2143 | if(isGray16(srcFormat) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8))) | |
2144 | { | |
2145 | c->swScale= gray16togray; | |
2146 | } | |
2147 | if((isPlanarYUV(srcFormat) || (srcFormat == PIX_FMT_GRAY8)) && isGray16(dstFormat)) | |
2148 | { | |
2149 | c->swScale= graytogray16; | |
2150 | } | |
2151 | if(srcFormat != dstFormat && isGray16(srcFormat) && isGray16(dstFormat)) | |
2152 | { | |
2153 | c->swScale= gray16swap; | |
6a4970ab | 2154 | } |
4884b9e5 | 2155 | |
e09d12f4 | 2156 | if(c->swScale){ |
ec22603f | 2157 | if(flags&SWS_PRINT_INFO) |
6a4970ab | 2158 | av_log(c, AV_LOG_INFO, "SwScaler: using unscaled %s -> %s special converter\n", |
94c4def2 | 2159 | sws_format_name(srcFormat), sws_format_name(dstFormat)); |
ec22603f MN |
2160 | return c; |
2161 | } | |
37079906 MN |
2162 | } |
2163 | ||
516b1f82 | 2164 | if(flags & SWS_CPU_CAPS_MMX2) |
28bf81c9 MN |
2165 | { |
2166 | c->canMMX2BeUsed= (dstW >=srcW && (dstW&31)==0 && (srcW&15)==0) ? 1 : 0; | |
2167 | if(!c->canMMX2BeUsed && dstW >=srcW && (srcW&15)==0 && (flags&SWS_FAST_BILINEAR)) | |
2168 | { | |
2169 | if(flags&SWS_PRINT_INFO) | |
2d529db5 | 2170 | av_log(c, AV_LOG_INFO, "SwScaler: output Width is not a multiple of 32 -> no MMX2 scaler\n"); |
28bf81c9 | 2171 | } |
ec62c38f | 2172 | if(usesHFilter) c->canMMX2BeUsed=0; |
28bf81c9 MN |
2173 | } |
2174 | else | |
2175 | c->canMMX2BeUsed=0; | |
2176 | ||
1e621b18 MN |
2177 | c->chrXInc= ((c->chrSrcW<<16) + (c->chrDstW>>1))/c->chrDstW; |
2178 | c->chrYInc= ((c->chrSrcH<<16) + (c->chrDstH>>1))/c->chrDstH; | |
2179 | ||
28bf81c9 MN |
2180 | // match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src to pixel n-2 of dst |
2181 | // but only for the FAST_BILINEAR mode otherwise do correct scaling | |
2182 | // n-2 is the last chrominance sample available | |
2183 | // this is not perfect, but noone shuld notice the difference, the more correct variant | |
2184 | // would be like the vertical one, but that would require some special code for the | |
2185 | // first and last pixel | |
2186 | if(flags&SWS_FAST_BILINEAR) | |
2187 | { | |
1e621b18 MN |
2188 | if(c->canMMX2BeUsed) |
2189 | { | |
2190 | c->lumXInc+= 20; | |
2191 | c->chrXInc+= 20; | |
2192 | } | |
77a416e8 | 2193 | //we don't use the x86asm scaler if mmx is available |
516b1f82 | 2194 | else if(flags & SWS_CPU_CAPS_MMX) |
1e621b18 MN |
2195 | { |
2196 | c->lumXInc = ((srcW-2)<<16)/(dstW-2) - 20; | |
2197 | c->chrXInc = ((c->chrSrcW-2)<<16)/(c->chrDstW-2) - 20; | |
2198 | } | |
28bf81c9 MN |
2199 | } |
2200 | ||
28bf81c9 MN |
2201 | /* precalculate horizontal scaler filter coefficients */ |
2202 | { | |
8c266f0c RD |
2203 | const int filterAlign= |
2204 | (flags & SWS_CPU_CAPS_MMX) ? 4 : | |
2205 | (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 : | |
2206 | 1; | |
28bf81c9 | 2207 | |
c7f822d9 | 2208 | initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc, |
81a571a8 MN |
2209 | srcW , dstW, filterAlign, 1<<14, |
2210 | (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags, | |
66d1cdb6 | 2211 | srcFilter->lumH, dstFilter->lumH, c->param); |
c7f822d9 | 2212 | initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, |
81a571a8 MN |
2213 | c->chrSrcW, c->chrDstW, filterAlign, 1<<14, |
2214 | (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, | |
66d1cdb6 | 2215 | srcFilter->chrH, dstFilter->chrH, c->param); |
28bf81c9 | 2216 | |
dbdae6ec | 2217 | #define MAX_FUNNY_CODE_SIZE 10000 |
17c613ef | 2218 | #if defined(COMPILE_MMX2) |
77a416e8 | 2219 | // can't downscale !!! |
28bf81c9 MN |
2220 | if(c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) |
2221 | { | |
113ef149 | 2222 | #ifdef MAP_ANONYMOUS |
38d5c282 AJ |
2223 | c->funnyYCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); |
2224 | c->funnyUVCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); | |
2225 | #else | |
8dfe9094 RD |
2226 | c->funnyYCode = av_malloc(MAX_FUNNY_CODE_SIZE); |
2227 | c->funnyUVCode = av_malloc(MAX_FUNNY_CODE_SIZE); | |
38d5c282 AJ |
2228 | #endif |
2229 | ||
8dfe9094 RD |
2230 | c->lumMmx2Filter = av_malloc((dstW /8+8)*sizeof(int16_t)); |
2231 | c->chrMmx2Filter = av_malloc((c->chrDstW /4+8)*sizeof(int16_t)); | |
2232 | c->lumMmx2FilterPos= av_malloc((dstW /2/8+8)*sizeof(int32_t)); | |
2233 | c->chrMmx2FilterPos= av_malloc((c->chrDstW/2/4+8)*sizeof(int32_t)); | |
b7dc6f66 MN |
2234 | |
2235 | initMMX2HScaler( dstW, c->lumXInc, c->funnyYCode , c->lumMmx2Filter, c->lumMmx2FilterPos, 8); | |
2236 | initMMX2HScaler(c->chrDstW, c->chrXInc, c->funnyUVCode, c->chrMmx2Filter, c->chrMmx2FilterPos, 4); | |
28bf81c9 | 2237 | } |
17c613ef | 2238 | #endif /* defined(COMPILE_MMX2) */ |
28bf81c9 MN |
2239 | } // Init Horizontal stuff |
2240 | ||
2241 | ||
2242 | ||
2243 | /* precalculate vertical scaler filter coefficients */ | |
8c266f0c RD |
2244 | { |
2245 | const int filterAlign= | |
bca11e75 | 2246 | (flags & SWS_CPU_CAPS_MMX) && (flags & SWS_ACCURATE_RND) ? 2 : |
8c266f0c RD |
2247 | (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 : |
2248 | 1; | |
2249 | ||
2250 | initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize, c->lumYInc, | |
2251 | srcH , dstH, filterAlign, (1<<12)-4, | |
2252 | (flags&SWS_BICUBLIN) ? (flags|SWS_BICUBIC) : flags, | |
66d1cdb6 | 2253 | srcFilter->lumV, dstFilter->lumV, c->param); |
8c266f0c RD |
2254 | initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc, |
2255 | c->chrSrcH, c->chrDstH, filterAlign, (1<<12)-4, | |
2256 | (flags&SWS_BICUBLIN) ? (flags|SWS_BILINEAR) : flags, | |
66d1cdb6 | 2257 | srcFilter->chrV, dstFilter->chrV, c->param); |
d33d485e AC |
2258 | |
2259 | #ifdef HAVE_ALTIVEC | |
8dfe9094 | 2260 | c->vYCoeffsBank = av_malloc(sizeof (vector signed short)*c->vLumFilterSize*c->dstH); |
d8cfa553 | 2261 | c->vCCoeffsBank = av_malloc(sizeof (vector signed short)*c->vChrFilterSize*c->chrDstH); |
d33d485e AC |
2262 | |
2263 | for (i=0;i<c->vLumFilterSize*c->dstH;i++) { | |
2264 | int j; | |
2265 | short *p = (short *)&c->vYCoeffsBank[i]; | |
2266 | for (j=0;j<8;j++) | |
2267 | p[j] = c->vLumFilter[i]; | |
2268 | } | |
2269 | ||
247d2c96 | 2270 | for (i=0;i<c->vChrFilterSize*c->chrDstH;i++) { |
d33d485e AC |
2271 | int j; |
2272 | short *p = (short *)&c->vCCoeffsBank[i]; | |
2273 | for (j=0;j<8;j++) | |
2274 | p[j] = c->vChrFilter[i]; | |
2275 | } | |
2276 | #endif | |
8c266f0c | 2277 | } |
28bf81c9 | 2278 | |
77a416e8 | 2279 | // Calculate Buffer Sizes so that they won't run out while handling these damn slices |
28bf81c9 MN |
2280 | c->vLumBufSize= c->vLumFilterSize; |
2281 | c->vChrBufSize= c->vChrFilterSize; | |
2282 | for(i=0; i<dstH; i++) | |
2283 | { | |
2284 | int chrI= i*c->chrDstH / dstH; | |
6f209cb5 | 2285 | int nextSlice= FFMAX(c->vLumFilterPos[i ] + c->vLumFilterSize - 1, |
e616aa93 | 2286 | ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)<<c->chrSrcVSubSample)); |
c4f1e443 MN |
2287 | |
2288 | nextSlice>>= c->chrSrcVSubSample; | |
2289 | nextSlice<<= c->chrSrcVSubSample; | |
28bf81c9 MN |
2290 | if(c->vLumFilterPos[i ] + c->vLumBufSize < nextSlice) |
2291 | c->vLumBufSize= nextSlice - c->vLumFilterPos[i ]; | |
e616aa93 MN |
2292 | if(c->vChrFilterPos[chrI] + c->vChrBufSize < (nextSlice>>c->chrSrcVSubSample)) |
2293 | c->vChrBufSize= (nextSlice>>c->chrSrcVSubSample) - c->vChrFilterPos[chrI]; | |
28bf81c9 MN |
2294 | } |
2295 | ||
2296 | // allocate pixbufs (we use dynamic allocation because otherwise we would need to | |
8dfe9094 RD |
2297 | c->lumPixBuf= av_malloc(c->vLumBufSize*2*sizeof(int16_t*)); |
2298 | c->chrPixBuf= av_malloc(c->vChrBufSize*2*sizeof(int16_t*)); | |
6c7506de | 2299 | //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) |
5edb653b | 2300 | /* align at 16 bytes for AltiVec */ |
28bf81c9 | 2301 | for(i=0; i<c->vLumBufSize; i++) |
0dea6433 | 2302 | c->lumPixBuf[i]= c->lumPixBuf[i+c->vLumBufSize]= av_mallocz(4000); |
28bf81c9 | 2303 | for(i=0; i<c->vChrBufSize; i++) |
8dfe9094 | 2304 | c->chrPixBuf[i]= c->chrPixBuf[i+c->vChrBufSize]= av_malloc(8000); |
28bf81c9 MN |
2305 | |
2306 | //try to avoid drawing green stuff between the right end and the stride end | |
28bf81c9 MN |
2307 | for(i=0; i<c->vChrBufSize; i++) memset(c->chrPixBuf[i], 64, 8000); |
2308 | ||
2309 | ASSERT(c->chrDstH <= dstH) | |
28bf81c9 | 2310 | |
28bf81c9 MN |
2311 | if(flags&SWS_PRINT_INFO) |
2312 | { | |
2313 | #ifdef DITHER1XBPP | |
5521b193 MN |
2314 | char *dither= " dithered"; |
2315 | #else | |
2316 | char *dither= ""; | |
28bf81c9 MN |
2317 | #endif |
2318 | if(flags&SWS_FAST_BILINEAR) | |
2d529db5 | 2319 | av_log(c, AV_LOG_INFO, "SwScaler: FAST_BILINEAR scaler, "); |
28bf81c9 | 2320 | else if(flags&SWS_BILINEAR) |
2d529db5 | 2321 | av_log(c, AV_LOG_INFO, "SwScaler: BILINEAR scaler, "); |
28bf81c9 | 2322 | else if(flags&SWS_BICUBIC) |
2d529db5 | 2323 | av_log(c, AV_LOG_INFO, "SwScaler: BICUBIC scaler, "); |
1e621b18 | 2324 | else if(flags&SWS_X) |
2d529db5 | 2325 | av_log(c, AV_LOG_INFO, "SwScaler: Experimental scaler, "); |
ff7ba856 | 2326 | else if(flags&SWS_POINT) |
2d529db5 | 2327 | av_log(c, AV_LOG_INFO, "SwScaler: Nearest Neighbor / POINT scaler, "); |
d8863d37 | 2328 | else if(flags&SWS_AREA) |
2d529db5 | 2329 | av_log(c, AV_LOG_INFO, "SwScaler: Area Averageing scaler, "); |
81a571a8 | 2330 | else if(flags&SWS_BICUBLIN) |
2d529db5 | 2331 | av_log(c, AV_LOG_INFO, "SwScaler: luma BICUBIC / chroma BILINEAR scaler, "); |
a86c461c | 2332 | else if(flags&SWS_GAUSS) |
2d529db5 | 2333 | av_log(c, AV_LOG_INFO, "SwScaler: Gaussian scaler, "); |
a86c461c | 2334 | else if(flags&SWS_SINC) |
2d529db5 | 2335 | av_log(c, AV_LOG_INFO, "SwScaler: Sinc scaler, "); |
a86c461c | 2336 | else if(flags&SWS_LANCZOS) |
2d529db5 | 2337 | av_log(c, AV_LOG_INFO, "SwScaler: Lanczos scaler, "); |
a86c461c | 2338 | else if(flags&SWS_SPLINE) |
2d529db5 | 2339 | av_log(c, AV_LOG_INFO, "SwScaler: Bicubic spline scaler, "); |
28bf81c9 | 2340 | else |
2d529db5 | 2341 | av_log(c, AV_LOG_INFO, "SwScaler: ehh flags invalid?! "); |
28bf81c9 | 2342 | |
e9e12f0e | 2343 | if(dstFormat==PIX_FMT_BGR555 || dstFormat==PIX_FMT_BGR565) |
6a4970ab | 2344 | av_log(c, AV_LOG_INFO, "from %s to%s %s ", |
94c4def2 | 2345 | sws_format_name(srcFormat), dither, sws_format_name(dstFormat)); |
0d9f3d85 | 2346 | else |
6a4970ab | 2347 | av_log(c, AV_LOG_INFO, "from %s to %s ", |
94c4def2 | 2348 | sws_format_name(srcFormat), sws_format_name(dstFormat)); |
28bf81c9 | 2349 | |
516b1f82 | 2350 | if(flags & SWS_CPU_CAPS_MMX2) |
2d529db5 | 2351 | av_log(c, AV_LOG_INFO, "using MMX2\n"); |
516b1f82 | 2352 | else if(flags & SWS_CPU_CAPS_3DNOW) |
2d529db5 | 2353 | av_log(c, AV_LOG_INFO, "using 3DNOW\n"); |
516b1f82 | 2354 | else if(flags & SWS_CPU_CAPS_MMX) |
2d529db5 | 2355 | av_log(c, AV_LOG_INFO, "using MMX\n"); |
a2faa401 | 2356 | else if(flags & SWS_CPU_CAPS_ALTIVEC) |
2d529db5 | 2357 | av_log(c, AV_LOG_INFO, "using AltiVec\n"); |
6a4970ab | 2358 | else |
2d529db5 | 2359 | av_log(c, AV_LOG_INFO, "using C\n"); |
28bf81c9 MN |
2360 | } |
2361 | ||
516b1f82 | 2362 | if(flags & SWS_PRINT_INFO) |
28bf81c9 | 2363 | { |
516b1f82 | 2364 | if(flags & SWS_CPU_CAPS_MMX) |
28bf81c9 MN |
2365 | { |
2366 | if(c->canMMX2BeUsed && (flags&SWS_FAST_BILINEAR)) | |
2d529db5 | 2367 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using FAST_BILINEAR MMX2 scaler for horizontal scaling\n"); |
28bf81c9 MN |
2368 | else |
2369 | { | |
2370 | if(c->hLumFilterSize==4) | |
2d529db5 | 2371 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 4-tap MMX scaler for horizontal luminance scaling\n"); |
28bf81c9 | 2372 | else if(c->hLumFilterSize==8) |
2d529db5 | 2373 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 8-tap MMX scaler for horizontal luminance scaling\n"); |
28bf81c9 | 2374 | else |
2d529db5 | 2375 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap MMX scaler for horizontal luminance scaling\n"); |
28bf81c9 MN |
2376 | |
2377 | if(c->hChrFilterSize==4) | |
2d529db5 | 2378 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 4-tap MMX scaler for horizontal chrominance scaling\n"); |
28bf81c9 | 2379 | else if(c->hChrFilterSize==8) |
2d529db5 | 2380 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 8-tap MMX scaler for horizontal chrominance scaling\n"); |
28bf81c9 | 2381 | else |
2d529db5 | 2382 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap MMX scaler for horizontal chrominance scaling\n"); |
28bf81c9 MN |
2383 | } |
2384 | } | |
2385 | else | |
2386 | { | |
3d6a30d9 | 2387 | #if defined(ARCH_X86) |
2d529db5 | 2388 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using X86-Asm scaler for horizontal scaling\n"); |
28bf81c9 MN |
2389 | #else |
2390 | if(flags & SWS_FAST_BILINEAR) | |
2d529db5 | 2391 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using FAST_BILINEAR C scaler for horizontal scaling\n"); |
28bf81c9 | 2392 | else |
2d529db5 | 2393 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using C scaler for horizontal scaling\n"); |
28bf81c9 MN |
2394 | #endif |
2395 | } | |
6c7506de | 2396 | if(isPlanarYUV(dstFormat)) |
28bf81c9 MN |
2397 | { |
2398 | if(c->vLumFilterSize==1) | |
2d529db5 | 2399 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 1-tap %s \"scaler\" for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 | 2400 | else |
2d529db5 | 2401 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap %s scaler for vertical scaling (YV12 like)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 MN |
2402 | } |
2403 | else | |
2404 | { | |
2405 | if(c->vLumFilterSize==1 && c->vChrFilterSize==2) | |
2d529db5 | 2406 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 1-tap %s \"scaler\" for vertical luminance scaling (BGR)\n" |
516b1f82 | 2407 | "SwScaler: 2-tap scaler for vertical chrominance scaling (BGR)\n",(flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 | 2408 | else if(c->vLumFilterSize==2 && c->vChrFilterSize==2) |
2d529db5 | 2409 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using 2-tap linear %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 | 2410 | else |
2d529db5 | 2411 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using n-tap %s scaler for vertical scaling (BGR)\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 MN |
2412 | } |
2413 | ||
e9e12f0e | 2414 | if(dstFormat==PIX_FMT_BGR24) |
2d529db5 | 2415 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR24 Converter\n", |
516b1f82 | 2416 | (flags & SWS_CPU_CAPS_MMX2) ? "MMX2" : ((flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C")); |
e9e12f0e | 2417 | else if(dstFormat==PIX_FMT_RGB32) |
2d529db5 | 2418 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR32 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
e9e12f0e | 2419 | else if(dstFormat==PIX_FMT_BGR565) |
2d529db5 | 2420 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR16 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
e9e12f0e | 2421 | else if(dstFormat==PIX_FMT_BGR555) |
2d529db5 | 2422 | av_log(c, AV_LOG_VERBOSE, "SwScaler: using %s YV12->BGR15 Converter\n", (flags & SWS_CPU_CAPS_MMX) ? "MMX" : "C"); |
28bf81c9 | 2423 | |
2d529db5 | 2424 | av_log(c, AV_LOG_VERBOSE, "SwScaler: %dx%d -> %dx%d\n", srcW, srcH, dstW, dstH); |
28bf81c9 | 2425 | } |
516b1f82 | 2426 | if(flags & SWS_PRINT_INFO) |
1e621b18 | 2427 | { |
2d529db5 | 2428 | av_log(c, AV_LOG_DEBUG, "SwScaler:Lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", |
1e621b18 | 2429 | c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc); |
2d529db5 | 2430 | av_log(c, AV_LOG_DEBUG, "SwScaler:Chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", |
1e621b18 MN |
2431 | c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, c->chrXInc, c->chrYInc); |
2432 | } | |
37079906 | 2433 | |
516b1f82 | 2434 | c->swScale= getSwsFunc(flags); |
28bf81c9 MN |
2435 | return c; |
2436 | } | |
2437 | ||
2438 | /** | |
77a416e8 | 2439 | * swscale warper, so we don't need to export the SwsContext. |
fccb9b2b MN |
2440 | * assumes planar YUV to be in YUV order instead of YVU |
2441 | */ | |
703b56fb | 2442 | int sws_scale(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
fccb9b2b | 2443 | int srcSliceH, uint8_t* dst[], int dstStride[]){ |
21c08a3f MN |
2444 | int i; |
2445 | uint8_t* src2[4]= {src[0], src[1], src[2]}; | |
2446 | uint32_t pal[256]; | |
e63ac25d | 2447 | if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { |
2d529db5 | 2448 | av_log(c, AV_LOG_ERROR, "swScaler: slices start in the middle!\n"); |
e63ac25d JM |
2449 | return 0; |
2450 | } | |
2451 | if (c->sliceDir == 0) { | |
2452 | if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1; | |
2453 | } | |
2454 | ||
21c08a3f MN |
2455 | if(c->srcFormat == PIX_FMT_PAL8){ |
2456 | for(i=0; i<256; i++){ | |
2457 | int p= ((uint32_t*)(src[1]))[i]; | |
2458 | int r= (p>>16)&0xFF; | |
2459 | int g= (p>> 8)&0xFF; | |
2460 | int b= p &0xFF; | |
2461 | int y= av_clip_uint8(((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16 ); | |
2462 | int u= av_clip_uint8(((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128); | |
2463 | int v= av_clip_uint8(((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128); | |
2464 | pal[i]= y + (u<<8) + (v<<16); | |
2465 | } | |
2466 | src2[1]= pal; | |
2467 | } | |
2468 | ||
e63ac25d JM |
2469 | // copy strides, so they can safely be modified |
2470 | if (c->sliceDir == 1) { | |
2471 | // slices go from top to bottom | |
dd9bdeb9 MN |
2472 | int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2]}; |
2473 | int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2]}; | |
0c840013 | 2474 | return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst, dstStride2); |
e63ac25d JM |
2475 | } else { |
2476 | // slices go from bottom to top => we flip the image internally | |
dd9bdeb9 | 2477 | uint8_t* dst2[4]= {dst[0] + (c->dstH-1)*dstStride[0], |
e63ac25d JM |
2478 | dst[1] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1], |
2479 | dst[2] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]}; | |
dd9bdeb9 MN |
2480 | int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2]}; |
2481 | int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2]}; | |
21c08a3f MN |
2482 | |
2483 | src2[0] += (srcSliceH-1)*srcStride[0]; | |
2484 | if(c->srcFormat != PIX_FMT_PAL8) | |
2485 | src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1]; | |
2486 | src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2]; | |
6a4970ab | 2487 | |
e63ac25d JM |
2488 | return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2); |
2489 | } | |
fccb9b2b MN |
2490 | } |
2491 | ||
2492 | /** | |
77a416e8 | 2493 | * swscale warper, so we don't need to export the SwsContext |
d4e24275 | 2494 | */ |
703b56fb LA |
2495 | int sws_scale_ordered(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, |
2496 | int srcSliceH, uint8_t* dst[], int dstStride[]){ | |
2497 | return sws_scale(c, src, srcStride, srcSliceY, srcSliceH, dst, dstStride); | |
d4e24275 | 2498 | } |
d4e24275 | 2499 | |
6a4970ab | 2500 | SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, |
e21206a8 MN |
2501 | float lumaSharpen, float chromaSharpen, |
2502 | float chromaHShift, float chromaVShift, | |
2503 | int verbose) | |
2504 | { | |
94c4def2 | 2505 | SwsFilter *filter= av_malloc(sizeof(SwsFilter)); |
e21206a8 MN |
2506 | |
2507 | if(lumaGBlur!=0.0){ | |
2508 | filter->lumH= sws_getGaussianVec(lumaGBlur, 3.0); | |
2509 | filter->lumV= sws_getGaussianVec(lumaGBlur, 3.0); | |
2510 | }else{ | |
2511 | filter->lumH= sws_getIdentityVec(); | |
2512 | filter->lumV= sws_getIdentityVec(); | |
2513 | } | |
2514 | ||
2515 | if(chromaGBlur!=0.0){ | |
2516 | filter->chrH= sws_getGaussianVec(chromaGBlur, 3.0); | |
2517 | filter->chrV= sws_getGaussianVec(chromaGBlur, 3.0); | |
2518 | }else{ | |
2519 | filter->chrH= sws_getIdentityVec(); | |
2520 | filter->chrV= sws_getIdentityVec(); | |
2521 | } | |
2522 | ||
2523 | if(chromaSharpen!=0.0){ | |
2e728364 MN |
2524 | SwsVector *id= sws_getIdentityVec(); |
2525 | sws_scaleVec(filter->chrH, -chromaSharpen); | |
2526 | sws_scaleVec(filter->chrV, -chromaSharpen); | |
2527 | sws_addVec(filter->chrH, id); | |
2528 | sws_addVec(filter->chrV, id); | |
e21206a8 MN |
2529 | sws_freeVec(id); |
2530 | } | |
2531 | ||
2532 | if(lumaSharpen!=0.0){ | |
2e728364 MN |
2533 | SwsVector *id= sws_getIdentityVec(); |
2534 | sws_scaleVec(filter->lumH, -lumaSharpen); | |
2535 | sws_scaleVec(filter->lumV, -lumaSharpen); | |
2536 | sws_addVec(filter->lumH, id); | |
2537 | sws_addVec(filter->lumV, id); | |
e21206a8 MN |
2538 | sws_freeVec(id); |
2539 | } | |
2540 | ||
2541 | if(chromaHShift != 0.0) | |
2542 | sws_shiftVec(filter->chrH, (int)(chromaHShift+0.5)); | |
2543 | ||
2544 | if(chromaVShift != 0.0) | |
2545 | sws_shiftVec(filter->chrV, (int)(chromaVShift+0.5)); | |
2546 | ||
2547 | sws_normalizeVec(filter->chrH, 1.0); | |
2548 | sws_normalizeVec(filter->chrV, 1.0); | |
2549 | sws_normalizeVec(filter->lumH, 1.0); | |
2550 | sws_normalizeVec(filter->lumV, 1.0); | |
2551 | ||
2552 | if(verbose) sws_printVec(filter->chrH); | |
2553 | if(verbose) sws_printVec(filter->lumH); | |
2554 | ||
2555 | return filter; | |
2556 | } | |
2557 | ||
d4e24275 | 2558 | /** |
28bf81c9 MN |
2559 | * returns a normalized gaussian curve used to filter stuff |
2560 | * quality=3 is high quality, lowwer is lowwer quality | |
2561 | */ | |
d4e24275 | 2562 | SwsVector *sws_getGaussianVec(double variance, double quality){ |
28bf81c9 MN |
2563 | const int length= (int)(variance*quality + 0.5) | 1; |
2564 | int i; | |
8dfe9094 | 2565 | double *coeff= av_malloc(length*sizeof(double)); |
28bf81c9 | 2566 | double middle= (length-1)*0.5; |
94c4def2 | 2567 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
c7f822d9 MN |
2568 | |
2569 | vec->coeff= coeff; | |
2570 | vec->length= length; | |
28bf81c9 MN |
2571 | |
2572 | for(i=0; i<length; i++) | |
2573 | { | |
2574 | double dist= i-middle; | |
2575 | coeff[i]= exp( -dist*dist/(2*variance*variance) ) / sqrt(2*variance*PI); | |
2576 | } | |
2577 | ||
d4e24275 | 2578 | sws_normalizeVec(vec, 1.0); |
c7f822d9 MN |
2579 | |
2580 | return vec; | |
28bf81c9 MN |
2581 | } |
2582 | ||
d4e24275 | 2583 | SwsVector *sws_getConstVec(double c, int length){ |
5521b193 | 2584 | int i; |
8dfe9094 | 2585 | double *coeff= av_malloc(length*sizeof(double)); |
94c4def2 | 2586 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
5521b193 MN |
2587 | |
2588 | vec->coeff= coeff; | |
2589 | vec->length= length; | |
2590 | ||
2591 | for(i=0; i<length; i++) | |
2592 | coeff[i]= c; | |
2593 | ||
2594 | return vec; | |
2595 | } | |
2596 | ||
2597 | ||
d4e24275 | 2598 | SwsVector *sws_getIdentityVec(void){ |
2e728364 | 2599 | return sws_getConstVec(1.0, 1); |
c7f822d9 MN |
2600 | } |
2601 | ||
2e728364 | 2602 | double sws_dcVec(SwsVector *a){ |
28bf81c9 | 2603 | int i; |
2e728364 | 2604 | double sum=0; |
28bf81c9 | 2605 | |
c7f822d9 MN |
2606 | for(i=0; i<a->length; i++) |
2607 | sum+= a->coeff[i]; | |
28bf81c9 | 2608 | |
2e728364 | 2609 | return sum; |
28bf81c9 MN |
2610 | } |
2611 | ||
d4e24275 | 2612 | void sws_scaleVec(SwsVector *a, double scalar){ |
c7f822d9 MN |
2613 | int i; |
2614 | ||
2615 | for(i=0; i<a->length; i++) | |
2616 | a->coeff[i]*= scalar; | |
2617 | } | |
2618 | ||
2e728364 MN |
2619 | void sws_normalizeVec(SwsVector *a, double height){ |
2620 | sws_scaleVec(a, height/sws_dcVec(a)); | |
2621 | } | |
2622 | ||
d4e24275 | 2623 | static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b){ |
c7f822d9 | 2624 | int length= a->length + b->length - 1; |
8dfe9094 | 2625 | double *coeff= av_malloc(length*sizeof(double)); |
28bf81c9 | 2626 | int i, j; |
94c4def2 | 2627 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
c7f822d9 MN |
2628 | |
2629 | vec->coeff= coeff; | |
2630 | vec->length= length; | |
28bf81c9 MN |
2631 | |
2632 | for(i=0; i<length; i++) coeff[i]= 0.0; | |
2633 | ||
c7f822d9 | 2634 | for(i=0; i<a->length; i++) |
28bf81c9 | 2635 | { |
c7f822d9 | 2636 | for(j=0; j<b->length; j++) |
28bf81c9 | 2637 | { |
c7f822d9 | 2638 | coeff[i+j]+= a->coeff[i]*b->coeff[j]; |
28bf81c9 MN |
2639 | } |
2640 | } | |
2641 | ||
c7f822d9 | 2642 | return vec; |
28bf81c9 MN |
2643 | } |
2644 | ||
d4e24275 | 2645 | static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b){ |
6f209cb5 | 2646 | int length= FFMAX(a->length, b->length); |
8dfe9094 | 2647 | double *coeff= av_malloc(length*sizeof(double)); |
28bf81c9 | 2648 | int i; |
94c4def2 | 2649 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
c7f822d9 MN |
2650 | |
2651 | vec->coeff= coeff; | |
2652 | vec->length= length; | |
28bf81c9 MN |
2653 | |
2654 | for(i=0; i<length; i++) coeff[i]= 0.0; | |
2655 | ||
c7f822d9 MN |
2656 | for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i]; |
2657 | for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]+= b->coeff[i]; | |
2658 | ||
2659 | return vec; | |
28bf81c9 | 2660 | } |
c7f822d9 | 2661 | |
d4e24275 | 2662 | static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b){ |
6f209cb5 | 2663 | int length= FFMAX(a->length, b->length); |
8dfe9094 | 2664 | double *coeff= av_malloc(length*sizeof(double)); |
c7f822d9 | 2665 | int i; |
94c4def2 | 2666 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
c7f822d9 MN |
2667 | |
2668 | vec->coeff= coeff; | |
2669 | vec->length= length; | |
2670 | ||
2671 | for(i=0; i<length; i++) coeff[i]= 0.0; | |
2672 | ||
2673 | for(i=0; i<a->length; i++) coeff[i + (length-1)/2 - (a->length-1)/2]+= a->coeff[i]; | |
2674 | for(i=0; i<b->length; i++) coeff[i + (length-1)/2 - (b->length-1)/2]-= b->coeff[i]; | |
2675 | ||
2676 | return vec; | |
2677 | } | |
2678 | ||
2679 | /* shift left / or right if "shift" is negative */ | |
d4e24275 | 2680 | static SwsVector *sws_getShiftedVec(SwsVector *a, int shift){ |
05749630 | 2681 | int length= a->length + FFABS(shift)*2; |
8dfe9094 | 2682 | double *coeff= av_malloc(length*sizeof(double)); |
ff7ba856 | 2683 | int i; |
94c4def2 | 2684 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
c7f822d9 MN |
2685 | |
2686 | vec->coeff= coeff; | |
2687 | vec->length= length; | |
2688 | ||
2689 | for(i=0; i<length; i++) coeff[i]= 0.0; | |
2690 | ||
2691 | for(i=0; i<a->length; i++) | |
2692 | { | |
2693 | coeff[i + (length-1)/2 - (a->length-1)/2 - shift]= a->coeff[i]; | |
2694 | } | |
2695 | ||
2696 | return vec; | |
2697 | } | |
2698 | ||
d4e24275 MN |
2699 | void sws_shiftVec(SwsVector *a, int shift){ |
2700 | SwsVector *shifted= sws_getShiftedVec(a, shift); | |
94c4def2 | 2701 | av_free(a->coeff); |
5cebb24b MN |
2702 | a->coeff= shifted->coeff; |
2703 | a->length= shifted->length; | |
94c4def2 | 2704 | av_free(shifted); |
5cebb24b MN |
2705 | } |
2706 | ||
d4e24275 MN |
2707 | void sws_addVec(SwsVector *a, SwsVector *b){ |
2708 | SwsVector *sum= sws_sumVec(a, b); | |
94c4def2 | 2709 | av_free(a->coeff); |
5cebb24b MN |
2710 | a->coeff= sum->coeff; |
2711 | a->length= sum->length; | |
94c4def2 | 2712 | av_free(sum); |
5cebb24b MN |
2713 | } |
2714 | ||
d4e24275 MN |
2715 | void sws_subVec(SwsVector *a, SwsVector *b){ |
2716 | SwsVector *diff= sws_diffVec(a, b); | |
94c4def2 | 2717 | av_free(a->coeff); |
5cebb24b MN |
2718 | a->coeff= diff->coeff; |
2719 | a->length= diff->length; | |
94c4def2 | 2720 | av_free(diff); |
5cebb24b MN |
2721 | } |
2722 | ||
d4e24275 MN |
2723 | void sws_convVec(SwsVector *a, SwsVector *b){ |
2724 | SwsVector *conv= sws_getConvVec(a, b); | |
6a4970ab | 2725 | av_free(a->coeff); |
5cebb24b MN |
2726 | a->coeff= conv->coeff; |
2727 | a->length= conv->length; | |
94c4def2 | 2728 | av_free(conv); |
5cebb24b MN |
2729 | } |
2730 | ||
d4e24275 | 2731 | SwsVector *sws_cloneVec(SwsVector *a){ |
8dfe9094 | 2732 | double *coeff= av_malloc(a->length*sizeof(double)); |
5cebb24b | 2733 | int i; |
94c4def2 | 2734 | SwsVector *vec= av_malloc(sizeof(SwsVector)); |
5cebb24b MN |
2735 | |
2736 | vec->coeff= coeff; | |
2737 | vec->length= a->length; | |
2738 | ||
2739 | for(i=0; i<a->length; i++) coeff[i]= a->coeff[i]; | |
2740 | ||
2741 | return vec; | |
2742 | } | |
2743 | ||
d4e24275 | 2744 | void sws_printVec(SwsVector *a){ |
c7f822d9 MN |
2745 | int i; |
2746 | double max=0; | |
2747 | double min=0; | |
2748 | double range; | |
2749 | ||
2750 | for(i=0; i<a->length; i++) | |
2751 | if(a->coeff[i]>max) max= a->coeff[i]; | |
2752 | ||
2753 | for(i=0; i<a->length; i++) | |
2754 | if(a->coeff[i]<min) min= a->coeff[i]; | |
2755 | ||
2756 | range= max - min; | |
2757 | ||
2758 | for(i=0; i<a->length; i++) | |
2759 | { | |
2760 | int x= (int)((a->coeff[i]-min)*60.0/range +0.5); | |
2d529db5 LA |
2761 | av_log(NULL, AV_LOG_DEBUG, "%1.3f ", a->coeff[i]); |
2762 | for(;x>0; x--) av_log(NULL, AV_LOG_DEBUG, " "); | |
2763 | av_log(NULL, AV_LOG_DEBUG, "|\n"); | |
c7f822d9 MN |
2764 | } |
2765 | } | |
2766 | ||
d4e24275 | 2767 | void sws_freeVec(SwsVector *a){ |
c7f822d9 | 2768 | if(!a) return; |
94c4def2 | 2769 | av_free(a->coeff); |
c7f822d9 MN |
2770 | a->coeff=NULL; |
2771 | a->length=0; | |
94c4def2 | 2772 | av_free(a); |
c7f822d9 MN |
2773 | } |
2774 | ||
e21206a8 MN |
2775 | void sws_freeFilter(SwsFilter *filter){ |
2776 | if(!filter) return; | |
2777 | ||
2778 | if(filter->lumH) sws_freeVec(filter->lumH); | |
2779 | if(filter->lumV) sws_freeVec(filter->lumV); | |
2780 | if(filter->chrH) sws_freeVec(filter->chrH); | |
2781 | if(filter->chrV) sws_freeVec(filter->chrV); | |
94c4def2 | 2782 | av_free(filter); |
e21206a8 MN |
2783 | } |
2784 | ||
2785 | ||
d4e24275 | 2786 | void sws_freeContext(SwsContext *c){ |
c7f822d9 | 2787 | int i; |
c7f822d9 MN |
2788 | if(!c) return; |
2789 | ||
2790 | if(c->lumPixBuf) | |
2791 | { | |
6c7506de | 2792 | for(i=0; i<c->vLumBufSize; i++) |
c7f822d9 | 2793 | { |
94c4def2 | 2794 | av_free(c->lumPixBuf[i]); |
c7f822d9 MN |
2795 | c->lumPixBuf[i]=NULL; |
2796 | } | |
94c4def2 | 2797 | av_free(c->lumPixBuf); |
c7f822d9 MN |
2798 | c->lumPixBuf=NULL; |
2799 | } | |
2800 | ||
2801 | if(c->chrPixBuf) | |
2802 | { | |
6c7506de | 2803 | for(i=0; i<c->vChrBufSize; i++) |
c7f822d9 | 2804 | { |
94c4def2 | 2805 | av_free(c->chrPixBuf[i]); |
c7f822d9 MN |
2806 | c->chrPixBuf[i]=NULL; |
2807 | } | |
94c4def2 | 2808 | av_free(c->chrPixBuf); |
c7f822d9 MN |
2809 | c->chrPixBuf=NULL; |
2810 | } | |
2811 | ||
94c4def2 | 2812 | av_free(c->vLumFilter); |
c7f822d9 | 2813 | c->vLumFilter = NULL; |
94c4def2 | 2814 | av_free(c->vChrFilter); |
c7f822d9 | 2815 | c->vChrFilter = NULL; |
94c4def2 | 2816 | av_free(c->hLumFilter); |
c7f822d9 | 2817 | c->hLumFilter = NULL; |
94c4def2 | 2818 | av_free(c->hChrFilter); |
c7f822d9 | 2819 | c->hChrFilter = NULL; |
d33d485e | 2820 | #ifdef HAVE_ALTIVEC |
94c4def2 | 2821 | av_free(c->vYCoeffsBank); |
d33d485e | 2822 | c->vYCoeffsBank = NULL; |
94c4def2 | 2823 | av_free(c->vCCoeffsBank); |
d33d485e AC |
2824 | c->vCCoeffsBank = NULL; |
2825 | #endif | |
c7f822d9 | 2826 | |
94c4def2 | 2827 | av_free(c->vLumFilterPos); |
c7f822d9 | 2828 | c->vLumFilterPos = NULL; |
94c4def2 | 2829 | av_free(c->vChrFilterPos); |
c7f822d9 | 2830 | c->vChrFilterPos = NULL; |
94c4def2 | 2831 | av_free(c->hLumFilterPos); |
c7f822d9 | 2832 | c->hLumFilterPos = NULL; |
94c4def2 | 2833 | av_free(c->hChrFilterPos); |
c7f822d9 MN |
2834 | c->hChrFilterPos = NULL; |
2835 | ||
9bde778e | 2836 | #if defined(ARCH_X86) && defined(CONFIG_GPL) |
0ce5275d | 2837 | #ifdef MAP_ANONYMOUS |
38d5c282 AJ |
2838 | if(c->funnyYCode) munmap(c->funnyYCode, MAX_FUNNY_CODE_SIZE); |
2839 | if(c->funnyUVCode) munmap(c->funnyUVCode, MAX_FUNNY_CODE_SIZE); | |
2840 | #else | |
94c4def2 LA |
2841 | av_free(c->funnyYCode); |
2842 | av_free(c->funnyUVCode); | |
38d5c282 AJ |
2843 | #endif |
2844 | c->funnyYCode=NULL; | |
2845 | c->funnyUVCode=NULL; | |
3d6a30d9 | 2846 | #endif /* defined(ARCH_X86) */ |
38d5c282 | 2847 | |
94c4def2 | 2848 | av_free(c->lumMmx2Filter); |
b7dc6f66 | 2849 | c->lumMmx2Filter=NULL; |
94c4def2 | 2850 | av_free(c->chrMmx2Filter); |
b7dc6f66 | 2851 | c->chrMmx2Filter=NULL; |
94c4def2 | 2852 | av_free(c->lumMmx2FilterPos); |
b7dc6f66 | 2853 | c->lumMmx2FilterPos=NULL; |
94c4def2 | 2854 | av_free(c->chrMmx2FilterPos); |
b7dc6f66 | 2855 | c->chrMmx2FilterPos=NULL; |
94c4def2 | 2856 | av_free(c->yuvTable); |
cf7d1c1a | 2857 | c->yuvTable=NULL; |
b7dc6f66 | 2858 | |
94c4def2 | 2859 | av_free(c); |
c7f822d9 MN |
2860 | } |
2861 | ||
22e46959 VP |
2862 | /** |
2863 | * Checks if context is valid or reallocs a new one instead. | |
2864 | * If context is NULL, just calls sws_getContext() to get a new one. | |
2865 | * Otherwise, checks if the parameters are the same already saved in context. | |
2866 | * If that is the case, returns the current context. | |
2867 | * Otherwise, frees context and gets a new one. | |
2868 | * | |
2869 | * Be warned that srcFilter, dstFilter are not checked, they are | |
2870 | * asumed to remain valid. | |
2871 | */ | |
2872 | struct SwsContext *sws_getCachedContext(struct SwsContext *context, | |
2873 | int srcW, int srcH, int srcFormat, | |
2874 | int dstW, int dstH, int dstFormat, int flags, | |
2875 | SwsFilter *srcFilter, SwsFilter *dstFilter, double *param) | |
2876 | { | |
2877 | if (context != NULL) { | |
2878 | if ((context->srcW != srcW) || (context->srcH != srcH) || | |
2879 | (context->srcFormat != srcFormat) || | |
2880 | (context->dstW != dstW) || (context->dstH != dstH) || | |
2881 | (context->dstFormat != dstFormat) || (context->flags != flags) || | |
2882 | (context->param != param)) | |
2883 | { | |
2884 | sws_freeContext(context); | |
2885 | context = NULL; | |
2886 | } | |
2887 | } | |
2888 | if (context == NULL) { | |
2889 | return sws_getContext(srcW, srcH, srcFormat, | |
2890 | dstW, dstH, dstFormat, flags, | |
2891 | srcFilter, dstFilter, param); | |
2892 | } | |
2893 | return context; | |
2894 | } | |
2895 |