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