]> git.sesse.net Git - ffmpeg/blob - libswscale/utils.c
Merge commit '9e5e76ef9ea803432ef2782a3f528c3f5bab621e'
[ffmpeg] / libswscale / utils.c
1 /*
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
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "config.h"
22
23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
24 #define _DARWIN_C_SOURCE // needed for MAP_ANON
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <string.h>
29 #if HAVE_SYS_MMAN_H
30 #include <sys/mman.h>
31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
32 #define MAP_ANONYMOUS MAP_ANON
33 #endif
34 #endif
35 #if HAVE_VIRTUALALLOC
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #endif
39
40 #include "libavutil/attributes.h"
41 #include "libavutil/avassert.h"
42 #include "libavutil/avutil.h"
43 #include "libavutil/bswap.h"
44 #include "libavutil/cpu.h"
45 #include "libavutil/intreadwrite.h"
46 #include "libavutil/mathematics.h"
47 #include "libavutil/opt.h"
48 #include "libavutil/pixdesc.h"
49 #include "libavutil/x86/asm.h"
50 #include "libavutil/x86/cpu.h"
51 #include "rgb2rgb.h"
52 #include "swscale.h"
53 #include "swscale_internal.h"
54
55 unsigned swscale_version(void)
56 {
57     av_assert0(LIBSWSCALE_VERSION_MICRO >= 100);
58     return LIBSWSCALE_VERSION_INT;
59 }
60
61 const char *swscale_configuration(void)
62 {
63     return FFMPEG_CONFIGURATION;
64 }
65
66 const char *swscale_license(void)
67 {
68 #define LICENSE_PREFIX "libswscale license: "
69     return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
70 }
71
72 #define RET 0xC3 // near return opcode for x86
73
74 typedef struct FormatEntry {
75     int is_supported_in, is_supported_out;
76 } FormatEntry;
77
78 static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
79     [AV_PIX_FMT_YUV420P]     = { 1, 1 },
80     [AV_PIX_FMT_YUYV422]     = { 1, 1 },
81     [AV_PIX_FMT_RGB24]       = { 1, 1 },
82     [AV_PIX_FMT_BGR24]       = { 1, 1 },
83     [AV_PIX_FMT_YUV422P]     = { 1, 1 },
84     [AV_PIX_FMT_YUV444P]     = { 1, 1 },
85     [AV_PIX_FMT_YUV410P]     = { 1, 1 },
86     [AV_PIX_FMT_YUV411P]     = { 1, 1 },
87     [AV_PIX_FMT_GRAY8]       = { 1, 1 },
88     [AV_PIX_FMT_MONOWHITE]   = { 1, 1 },
89     [AV_PIX_FMT_MONOBLACK]   = { 1, 1 },
90     [AV_PIX_FMT_PAL8]        = { 1, 0 },
91     [AV_PIX_FMT_YUVJ420P]    = { 1, 1 },
92     [AV_PIX_FMT_YUVJ422P]    = { 1, 1 },
93     [AV_PIX_FMT_YUVJ444P]    = { 1, 1 },
94     [AV_PIX_FMT_UYVY422]     = { 1, 1 },
95     [AV_PIX_FMT_UYYVYY411]   = { 0, 0 },
96     [AV_PIX_FMT_BGR8]        = { 1, 1 },
97     [AV_PIX_FMT_BGR4]        = { 0, 1 },
98     [AV_PIX_FMT_BGR4_BYTE]   = { 1, 1 },
99     [AV_PIX_FMT_RGB8]        = { 1, 1 },
100     [AV_PIX_FMT_RGB4]        = { 0, 1 },
101     [AV_PIX_FMT_RGB4_BYTE]   = { 1, 1 },
102     [AV_PIX_FMT_NV12]        = { 1, 1 },
103     [AV_PIX_FMT_NV21]        = { 1, 1 },
104     [AV_PIX_FMT_ARGB]        = { 1, 1 },
105     [AV_PIX_FMT_RGBA]        = { 1, 1 },
106     [AV_PIX_FMT_ABGR]        = { 1, 1 },
107     [AV_PIX_FMT_BGRA]        = { 1, 1 },
108     [AV_PIX_FMT_0RGB]        = { 1, 1 },
109     [AV_PIX_FMT_RGB0]        = { 1, 1 },
110     [AV_PIX_FMT_0BGR]        = { 1, 1 },
111     [AV_PIX_FMT_BGR0]        = { 1, 1 },
112     [AV_PIX_FMT_GRAY16BE]    = { 1, 1 },
113     [AV_PIX_FMT_GRAY16LE]    = { 1, 1 },
114     [AV_PIX_FMT_YUV440P]     = { 1, 1 },
115     [AV_PIX_FMT_YUVJ440P]    = { 1, 1 },
116     [AV_PIX_FMT_YUVA420P]    = { 1, 1 },
117     [AV_PIX_FMT_YUVA422P]    = { 1, 1 },
118     [AV_PIX_FMT_YUVA444P]    = { 1, 1 },
119     [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 },
120     [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 },
121     [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 },
122     [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 },
123     [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 },
124     [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 },
125     [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 },
126     [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 },
127     [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 },
128     [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 },
129     [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 },
130     [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 },
131     [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 },
132     [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 },
133     [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 },
134     [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 },
135     [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 },
136     [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 },
137     [AV_PIX_FMT_RGB48BE]     = { 1, 1 },
138     [AV_PIX_FMT_RGB48LE]     = { 1, 1 },
139     [AV_PIX_FMT_RGBA64BE]    = { 1, 0 },
140     [AV_PIX_FMT_RGBA64LE]    = { 1, 0 },
141     [AV_PIX_FMT_RGB565BE]    = { 1, 1 },
142     [AV_PIX_FMT_RGB565LE]    = { 1, 1 },
143     [AV_PIX_FMT_RGB555BE]    = { 1, 1 },
144     [AV_PIX_FMT_RGB555LE]    = { 1, 1 },
145     [AV_PIX_FMT_BGR565BE]    = { 1, 1 },
146     [AV_PIX_FMT_BGR565LE]    = { 1, 1 },
147     [AV_PIX_FMT_BGR555BE]    = { 1, 1 },
148     [AV_PIX_FMT_BGR555LE]    = { 1, 1 },
149     [AV_PIX_FMT_YUV420P16LE] = { 1, 1 },
150     [AV_PIX_FMT_YUV420P16BE] = { 1, 1 },
151     [AV_PIX_FMT_YUV422P16LE] = { 1, 1 },
152     [AV_PIX_FMT_YUV422P16BE] = { 1, 1 },
153     [AV_PIX_FMT_YUV444P16LE] = { 1, 1 },
154     [AV_PIX_FMT_YUV444P16BE] = { 1, 1 },
155     [AV_PIX_FMT_RGB444LE]    = { 1, 1 },
156     [AV_PIX_FMT_RGB444BE]    = { 1, 1 },
157     [AV_PIX_FMT_BGR444LE]    = { 1, 1 },
158     [AV_PIX_FMT_BGR444BE]    = { 1, 1 },
159     [AV_PIX_FMT_Y400A]       = { 1, 0 },
160     [AV_PIX_FMT_BGR48BE]     = { 1, 1 },
161     [AV_PIX_FMT_BGR48LE]     = { 1, 1 },
162     [AV_PIX_FMT_BGRA64BE]    = { 0, 0 },
163     [AV_PIX_FMT_BGRA64LE]    = { 0, 0 },
164     [AV_PIX_FMT_YUV420P9BE]  = { 1, 1 },
165     [AV_PIX_FMT_YUV420P9LE]  = { 1, 1 },
166     [AV_PIX_FMT_YUV420P10BE] = { 1, 1 },
167     [AV_PIX_FMT_YUV420P10LE] = { 1, 1 },
168     [AV_PIX_FMT_YUV420P12BE] = { 1, 1 },
169     [AV_PIX_FMT_YUV420P12LE] = { 1, 1 },
170     [AV_PIX_FMT_YUV420P14BE] = { 1, 1 },
171     [AV_PIX_FMT_YUV420P14LE] = { 1, 1 },
172     [AV_PIX_FMT_YUV422P9BE]  = { 1, 1 },
173     [AV_PIX_FMT_YUV422P9LE]  = { 1, 1 },
174     [AV_PIX_FMT_YUV422P10BE] = { 1, 1 },
175     [AV_PIX_FMT_YUV422P10LE] = { 1, 1 },
176     [AV_PIX_FMT_YUV422P12BE] = { 1, 1 },
177     [AV_PIX_FMT_YUV422P12LE] = { 1, 1 },
178     [AV_PIX_FMT_YUV422P14BE] = { 1, 1 },
179     [AV_PIX_FMT_YUV422P14LE] = { 1, 1 },
180     [AV_PIX_FMT_YUV444P9BE]  = { 1, 1 },
181     [AV_PIX_FMT_YUV444P9LE]  = { 1, 1 },
182     [AV_PIX_FMT_YUV444P10BE] = { 1, 1 },
183     [AV_PIX_FMT_YUV444P10LE] = { 1, 1 },
184     [AV_PIX_FMT_YUV444P12BE] = { 1, 1 },
185     [AV_PIX_FMT_YUV444P12LE] = { 1, 1 },
186     [AV_PIX_FMT_YUV444P14BE] = { 1, 1 },
187     [AV_PIX_FMT_YUV444P14LE] = { 1, 1 },
188     [AV_PIX_FMT_GBRP]        = { 1, 1 },
189     [AV_PIX_FMT_GBRP9LE]     = { 1, 1 },
190     [AV_PIX_FMT_GBRP9BE]     = { 1, 1 },
191     [AV_PIX_FMT_GBRP10LE]    = { 1, 1 },
192     [AV_PIX_FMT_GBRP10BE]    = { 1, 1 },
193     [AV_PIX_FMT_GBRP12LE]    = { 1, 1 },
194     [AV_PIX_FMT_GBRP12BE]    = { 1, 1 },
195     [AV_PIX_FMT_GBRP14LE]    = { 1, 1 },
196     [AV_PIX_FMT_GBRP14BE]    = { 1, 1 },
197     [AV_PIX_FMT_GBRP16LE]    = { 1, 0 },
198     [AV_PIX_FMT_GBRP16BE]    = { 1, 0 },
199     [AV_PIX_FMT_XYZ12BE]     = { 1, 0 },
200     [AV_PIX_FMT_XYZ12LE]     = { 1, 0 },
201     [AV_PIX_FMT_GBRAP]       = { 0, 0 },
202     [AV_PIX_FMT_GBRAP16LE]   = { 0, 0 },
203     [AV_PIX_FMT_GBRAP16BE]   = { 0, 0 },
204 };
205
206 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
207 {
208     return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
209            format_entries[pix_fmt].is_supported_in : 0;
210 }
211
212 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
213 {
214     return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
215            format_entries[pix_fmt].is_supported_out : 0;
216 }
217
218 extern const int32_t ff_yuv2rgb_coeffs[8][4];
219
220 #if FF_API_SWS_FORMAT_NAME
221 const char *sws_format_name(enum AVPixelFormat format)
222 {
223     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
224     if (desc)
225         return desc->name;
226     else
227         return "Unknown format";
228 }
229 #endif
230
231 static double getSplineCoeff(double a, double b, double c, double d,
232                              double dist)
233 {
234     if (dist <= 1.0)
235         return ((d * dist + c) * dist + b) * dist + a;
236     else
237         return getSplineCoeff(0.0,
238                                b + 2.0 * c + 3.0 * d,
239                                c + 3.0 * d,
240                               -b - 3.0 * c - 6.0 * d,
241                               dist - 1.0);
242 }
243
244 static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos,
245                               int *outFilterSize, int xInc, int srcW,
246                               int dstW, int filterAlign, int one,
247                               int flags, int cpu_flags,
248                               SwsVector *srcFilter, SwsVector *dstFilter,
249                               double param[2])
250 {
251     int i;
252     int filterSize;
253     int filter2Size;
254     int minFilterSize;
255     int64_t *filter    = NULL;
256     int64_t *filter2   = NULL;
257     const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8));
258     int ret            = -1;
259
260     emms_c(); // FIXME should not be required but IS (even for non-MMX versions)
261
262     // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
263     FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW + 3) * sizeof(**filterPos), fail);
264
265     if (FFABS(xInc - 0x10000) < 10) { // unscaled
266         int i;
267         filterSize = 1;
268         FF_ALLOCZ_OR_GOTO(NULL, filter,
269                           dstW * sizeof(*filter) * filterSize, fail);
270
271         for (i = 0; i < dstW; i++) {
272             filter[i * filterSize] = fone;
273             (*filterPos)[i]        = i;
274         }
275     } else if (flags & SWS_POINT) { // lame looking point sampling mode
276         int i;
277         int64_t xDstInSrc;
278         filterSize = 1;
279         FF_ALLOC_OR_GOTO(NULL, filter,
280                          dstW * sizeof(*filter) * filterSize, fail);
281
282         xDstInSrc = xInc / 2 - 0x8000;
283         for (i = 0; i < dstW; i++) {
284             int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
285
286             (*filterPos)[i] = xx;
287             filter[i]       = fone;
288             xDstInSrc      += xInc;
289         }
290     } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) ||
291                (flags & SWS_FAST_BILINEAR)) { // bilinear upscale
292         int i;
293         int64_t xDstInSrc;
294         filterSize = 2;
295         FF_ALLOC_OR_GOTO(NULL, filter,
296                          dstW * sizeof(*filter) * filterSize, fail);
297
298         xDstInSrc = xInc / 2 - 0x8000;
299         for (i = 0; i < dstW; i++) {
300             int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
301             int j;
302
303             (*filterPos)[i] = xx;
304             // bilinear upscale / linear interpolate / area averaging
305             for (j = 0; j < filterSize; j++) {
306                 int64_t coeff= fone - FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16);
307                 if (coeff < 0)
308                     coeff = 0;
309                 filter[i * filterSize + j] = coeff;
310                 xx++;
311             }
312             xDstInSrc += xInc;
313         }
314     } else {
315         int64_t xDstInSrc;
316         int sizeFactor;
317
318         if (flags & SWS_BICUBIC)
319             sizeFactor = 4;
320         else if (flags & SWS_X)
321             sizeFactor = 8;
322         else if (flags & SWS_AREA)
323             sizeFactor = 1;     // downscale only, for upscale it is bilinear
324         else if (flags & SWS_GAUSS)
325             sizeFactor = 8;     // infinite ;)
326         else if (flags & SWS_LANCZOS)
327             sizeFactor = param[0] != SWS_PARAM_DEFAULT ? ceil(2 * param[0]) : 6;
328         else if (flags & SWS_SINC)
329             sizeFactor = 20;    // infinite ;)
330         else if (flags & SWS_SPLINE)
331             sizeFactor = 20;    // infinite ;)
332         else if (flags & SWS_BILINEAR)
333             sizeFactor = 2;
334         else {
335             av_assert0(0);
336         }
337
338         if (xInc <= 1 << 16)
339             filterSize = 1 + sizeFactor;    // upscale
340         else
341             filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
342
343         filterSize = FFMIN(filterSize, srcW - 2);
344         filterSize = FFMAX(filterSize, 1);
345
346         FF_ALLOC_OR_GOTO(NULL, filter,
347                          dstW * sizeof(*filter) * filterSize, fail);
348
349         xDstInSrc = xInc - 0x10000;
350         for (i = 0; i < dstW; i++) {
351             int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17);
352             int j;
353             (*filterPos)[i] = xx;
354             for (j = 0; j < filterSize; j++) {
355                 int64_t d = (FFABS(((int64_t)xx << 17) - xDstInSrc)) << 13;
356                 double floatd;
357                 int64_t coeff;
358
359                 if (xInc > 1 << 16)
360                     d = d * dstW / srcW;
361                 floatd = d * (1.0 / (1 << 30));
362
363                 if (flags & SWS_BICUBIC) {
364                     int64_t B = (param[0] != SWS_PARAM_DEFAULT ? param[0] :   0) * (1 << 24);
365                     int64_t C = (param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6) * (1 << 24);
366
367                     if (d >= 1LL << 31) {
368                         coeff = 0.0;
369                     } else {
370                         int64_t dd  = (d  * d) >> 30;
371                         int64_t ddd = (dd * d) >> 30;
372
373                         if (d < 1LL << 30)
374                             coeff =  (12 * (1 << 24) -  9 * B - 6 * C) * ddd +
375                                     (-18 * (1 << 24) + 12 * B + 6 * C) *  dd +
376                                       (6 * (1 << 24) -  2 * B)         * (1 << 30);
377                         else
378                             coeff =      (-B -  6 * C) * ddd +
379                                       (6 * B + 30 * C) * dd  +
380                                     (-12 * B - 48 * C) * d   +
381                                       (8 * B + 24 * C) * (1 << 30);
382                     }
383                     coeff /= (1LL<<54)/fone;
384                 }
385 #if 0
386                 else if (flags & SWS_X) {
387                     double p  = param ? param * 0.01 : 0.3;
388                     coeff     = d ? sin(d * M_PI) / (d * M_PI) : 1.0;
389                     coeff    *= pow(2.0, -p * d * d);
390                 }
391 #endif
392                 else if (flags & SWS_X) {
393                     double A = param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
394                     double c;
395
396                     if (floatd < 1.0)
397                         c = cos(floatd * M_PI);
398                     else
399                         c = -1.0;
400                     if (c < 0.0)
401                         c = -pow(-c, A);
402                     else
403                         c = pow(c, A);
404                     coeff = (c * 0.5 + 0.5) * fone;
405                 } else if (flags & SWS_AREA) {
406                     int64_t d2 = d - (1 << 29);
407                     if (d2 * xInc < -(1LL << (29 + 16)))
408                         coeff = 1.0 * (1LL << (30 + 16));
409                     else if (d2 * xInc < (1LL << (29 + 16)))
410                         coeff = -d2 * xInc + (1LL << (29 + 16));
411                     else
412                         coeff = 0.0;
413                     coeff *= fone >> (30 + 16);
414                 } else if (flags & SWS_GAUSS) {
415                     double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
416                     coeff = (pow(2.0, -p * floatd * floatd)) * fone;
417                 } else if (flags & SWS_SINC) {
418                     coeff = (d ? sin(floatd * M_PI) / (floatd * M_PI) : 1.0) * fone;
419                 } else if (flags & SWS_LANCZOS) {
420                     double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
421                     coeff = (d ? sin(floatd * M_PI) * sin(floatd * M_PI / p) /
422                              (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
423                     if (floatd > p)
424                         coeff = 0;
425                 } else if (flags & SWS_BILINEAR) {
426                     coeff = (1 << 30) - d;
427                     if (coeff < 0)
428                         coeff = 0;
429                     coeff *= fone >> 30;
430                 } else if (flags & SWS_SPLINE) {
431                     double p = -2.196152422706632;
432                     coeff = getSplineCoeff(1.0, 0.0, p, -p - 1.0, floatd) * fone;
433                 } else {
434                     av_assert0(0);
435                 }
436
437                 filter[i * filterSize + j] = coeff;
438                 xx++;
439             }
440             xDstInSrc += 2 * xInc;
441         }
442     }
443
444     /* apply src & dst Filter to filter -> filter2
445      * av_free(filter);
446      */
447     av_assert0(filterSize > 0);
448     filter2Size = filterSize;
449     if (srcFilter)
450         filter2Size += srcFilter->length - 1;
451     if (dstFilter)
452         filter2Size += dstFilter->length - 1;
453     av_assert0(filter2Size > 0);
454     FF_ALLOCZ_OR_GOTO(NULL, filter2, filter2Size * dstW * sizeof(*filter2), fail);
455
456     for (i = 0; i < dstW; i++) {
457         int j, k;
458
459         if (srcFilter) {
460             for (k = 0; k < srcFilter->length; k++) {
461                 for (j = 0; j < filterSize; j++)
462                     filter2[i * filter2Size + k + j] +=
463                         srcFilter->coeff[k] * filter[i * filterSize + j];
464             }
465         } else {
466             for (j = 0; j < filterSize; j++)
467                 filter2[i * filter2Size + j] = filter[i * filterSize + j];
468         }
469         // FIXME dstFilter
470
471         (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
472     }
473     av_freep(&filter);
474
475     /* try to reduce the filter-size (step1 find size and shift left) */
476     // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
477     minFilterSize = 0;
478     for (i = dstW - 1; i >= 0; i--) {
479         int min = filter2Size;
480         int j;
481         int64_t cutOff = 0.0;
482
483         /* get rid of near zero elements on the left by shifting left */
484         for (j = 0; j < filter2Size; j++) {
485             int k;
486             cutOff += FFABS(filter2[i * filter2Size]);
487
488             if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
489                 break;
490
491             /* preserve monotonicity because the core can't handle the
492              * filter otherwise */
493             if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
494                 break;
495
496             // move filter coefficients left
497             for (k = 1; k < filter2Size; k++)
498                 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
499             filter2[i * filter2Size + k - 1] = 0;
500             (*filterPos)[i]++;
501         }
502
503         cutOff = 0;
504         /* count near zeros on the right */
505         for (j = filter2Size - 1; j > 0; j--) {
506             cutOff += FFABS(filter2[i * filter2Size + j]);
507
508             if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
509                 break;
510             min--;
511         }
512
513         if (min > minFilterSize)
514             minFilterSize = min;
515     }
516
517     if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) {
518         // we can handle the special case 4, so we don't want to go the full 8
519         if (minFilterSize < 5)
520             filterAlign = 4;
521
522         /* We really don't want to waste our time doing useless computation, so
523          * fall back on the scalar C code for very small filters.
524          * Vectorizing is worth it only if you have a decent-sized vector. */
525         if (minFilterSize < 3)
526             filterAlign = 1;
527     }
528
529     if (INLINE_MMX(cpu_flags)) {
530         // special case for unscaled vertical filtering
531         if (minFilterSize == 1 && filterAlign == 2)
532             filterAlign = 1;
533     }
534
535     av_assert0(minFilterSize > 0);
536     filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
537     av_assert0(filterSize > 0);
538     filter = av_malloc(filterSize * dstW * sizeof(*filter));
539     if (filterSize >= MAX_FILTER_SIZE * 16 /
540                       ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16) || !filter) {
541         av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreem scaling or increase MAX_FILTER_SIZE and recompile\n", filterSize);
542         goto fail;
543     }
544     *outFilterSize = filterSize;
545
546     if (flags & SWS_PRINT_INFO)
547         av_log(NULL, AV_LOG_VERBOSE,
548                "SwScaler: reducing / aligning filtersize %d -> %d\n",
549                filter2Size, filterSize);
550     /* try to reduce the filter-size (step2 reduce it) */
551     for (i = 0; i < dstW; i++) {
552         int j;
553
554         for (j = 0; j < filterSize; j++) {
555             if (j >= filter2Size)
556                 filter[i * filterSize + j] = 0;
557             else
558                 filter[i * filterSize + j] = filter2[i * filter2Size + j];
559             if ((flags & SWS_BITEXACT) && j >= minFilterSize)
560                 filter[i * filterSize + j] = 0;
561         }
562     }
563
564     // FIXME try to align filterPos if possible
565
566     // fix borders
567     for (i = 0; i < dstW; i++) {
568         int j;
569         if ((*filterPos)[i] < 0) {
570             // move filter coefficients left to compensate for filterPos
571             for (j = 1; j < filterSize; j++) {
572                 int left = FFMAX(j + (*filterPos)[i], 0);
573                 filter[i * filterSize + left] += filter[i * filterSize + j];
574                 filter[i * filterSize + j]     = 0;
575             }
576             (*filterPos)[i]= 0;
577         }
578
579         if ((*filterPos)[i] + filterSize > srcW) {
580             int shift = (*filterPos)[i] + filterSize - srcW;
581             // move filter coefficients right to compensate for filterPos
582             for (j = filterSize - 2; j >= 0; j--) {
583                 int right = FFMIN(j + shift, filterSize - 1);
584                 filter[i * filterSize + right] += filter[i * filterSize + j];
585                 filter[i * filterSize + j]      = 0;
586             }
587             (*filterPos)[i]= srcW - filterSize;
588         }
589     }
590
591     // Note the +1 is for the MMX scaler which reads over the end
592     /* align at 16 for AltiVec (needed by hScale_altivec_real) */
593     FF_ALLOCZ_OR_GOTO(NULL, *outFilter,
594                       *outFilterSize * (dstW + 3) * sizeof(int16_t), fail);
595
596     /* normalize & store in outFilter */
597     for (i = 0; i < dstW; i++) {
598         int j;
599         int64_t error = 0;
600         int64_t sum   = 0;
601
602         for (j = 0; j < filterSize; j++) {
603             sum += filter[i * filterSize + j];
604         }
605         sum = (sum + one / 2) / one;
606         for (j = 0; j < *outFilterSize; j++) {
607             int64_t v = filter[i * filterSize + j] + error;
608             int intV  = ROUNDED_DIV(v, sum);
609             (*outFilter)[i * (*outFilterSize) + j] = intV;
610             error                                  = v - intV * sum;
611         }
612     }
613
614     (*filterPos)[dstW + 0] =
615     (*filterPos)[dstW + 1] =
616     (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1]; /* the MMX/SSE scaler will
617                                                       * read over the end */
618     for (i = 0; i < *outFilterSize; i++) {
619         int k = (dstW - 1) * (*outFilterSize) + i;
620         (*outFilter)[k + 1 * (*outFilterSize)] =
621         (*outFilter)[k + 2 * (*outFilterSize)] =
622         (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
623     }
624
625     ret = 0;
626
627 fail:
628     if(ret < 0)
629         av_log(NULL, AV_LOG_ERROR, "sws: initFilter failed\n");
630     av_free(filter);
631     av_free(filter2);
632     return ret;
633 }
634
635 #if HAVE_MMXEXT_INLINE
636 static av_cold int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode,
637                                        int16_t *filter, int32_t *filterPos,
638                                        int numSplits)
639 {
640     uint8_t *fragmentA;
641     x86_reg imm8OfPShufW1A;
642     x86_reg imm8OfPShufW2A;
643     x86_reg fragmentLengthA;
644     uint8_t *fragmentB;
645     x86_reg imm8OfPShufW1B;
646     x86_reg imm8OfPShufW2B;
647     x86_reg fragmentLengthB;
648     int fragmentPos;
649
650     int xpos, i;
651
652     // create an optimized horizontal scaling routine
653     /* This scaler is made of runtime-generated MMXEXT code using specially tuned
654      * pshufw instructions. For every four output pixels, if four input pixels
655      * are enough for the fast bilinear scaling, then a chunk of fragmentB is
656      * used. If five input pixels are needed, then a chunk of fragmentA is used.
657      */
658
659     // code fragment
660
661     __asm__ volatile (
662         "jmp                         9f                 \n\t"
663         // Begin
664         "0:                                             \n\t"
665         "movq    (%%"REG_d", %%"REG_a"), %%mm3          \n\t"
666         "movd    (%%"REG_c", %%"REG_S"), %%mm0          \n\t"
667         "movd   1(%%"REG_c", %%"REG_S"), %%mm1          \n\t"
668         "punpcklbw                %%mm7, %%mm1          \n\t"
669         "punpcklbw                %%mm7, %%mm0          \n\t"
670         "pshufw                   $0xFF, %%mm1, %%mm1   \n\t"
671         "1:                                             \n\t"
672         "pshufw                   $0xFF, %%mm0, %%mm0   \n\t"
673         "2:                                             \n\t"
674         "psubw                    %%mm1, %%mm0          \n\t"
675         "movl   8(%%"REG_b", %%"REG_a"), %%esi          \n\t"
676         "pmullw                   %%mm3, %%mm0          \n\t"
677         "psllw                       $7, %%mm1          \n\t"
678         "paddw                    %%mm1, %%mm0          \n\t"
679
680         "movq                     %%mm0, (%%"REG_D", %%"REG_a") \n\t"
681
682         "add                         $8, %%"REG_a"      \n\t"
683         // End
684         "9:                                             \n\t"
685         // "int $3                                         \n\t"
686         "lea       " LOCAL_MANGLE(0b) ", %0             \n\t"
687         "lea       " LOCAL_MANGLE(1b) ", %1             \n\t"
688         "lea       " LOCAL_MANGLE(2b) ", %2             \n\t"
689         "dec                         %1                 \n\t"
690         "dec                         %2                 \n\t"
691         "sub                         %0, %1             \n\t"
692         "sub                         %0, %2             \n\t"
693         "lea       " LOCAL_MANGLE(9b) ", %3             \n\t"
694         "sub                         %0, %3             \n\t"
695
696
697         : "=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
698           "=r" (fragmentLengthA)
699         );
700
701     __asm__ volatile (
702         "jmp                         9f                 \n\t"
703         // Begin
704         "0:                                             \n\t"
705         "movq    (%%"REG_d", %%"REG_a"), %%mm3          \n\t"
706         "movd    (%%"REG_c", %%"REG_S"), %%mm0          \n\t"
707         "punpcklbw                %%mm7, %%mm0          \n\t"
708         "pshufw                   $0xFF, %%mm0, %%mm1   \n\t"
709         "1:                                             \n\t"
710         "pshufw                   $0xFF, %%mm0, %%mm0   \n\t"
711         "2:                                             \n\t"
712         "psubw                    %%mm1, %%mm0          \n\t"
713         "movl   8(%%"REG_b", %%"REG_a"), %%esi          \n\t"
714         "pmullw                   %%mm3, %%mm0          \n\t"
715         "psllw                       $7, %%mm1          \n\t"
716         "paddw                    %%mm1, %%mm0          \n\t"
717
718         "movq                     %%mm0, (%%"REG_D", %%"REG_a") \n\t"
719
720         "add                         $8, %%"REG_a"      \n\t"
721         // End
722         "9:                                             \n\t"
723         // "int                       $3                   \n\t"
724         "lea       " LOCAL_MANGLE(0b) ", %0             \n\t"
725         "lea       " LOCAL_MANGLE(1b) ", %1             \n\t"
726         "lea       " LOCAL_MANGLE(2b) ", %2             \n\t"
727         "dec                         %1                 \n\t"
728         "dec                         %2                 \n\t"
729         "sub                         %0, %1             \n\t"
730         "sub                         %0, %2             \n\t"
731         "lea       " LOCAL_MANGLE(9b) ", %3             \n\t"
732         "sub                         %0, %3             \n\t"
733
734
735         : "=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
736           "=r" (fragmentLengthB)
737         );
738
739     xpos        = 0; // lumXInc/2 - 0x8000; // difference between pixel centers
740     fragmentPos = 0;
741
742     for (i = 0; i < dstW / numSplits; i++) {
743         int xx = xpos >> 16;
744
745         if ((i & 3) == 0) {
746             int a                  = 0;
747             int b                  = ((xpos + xInc) >> 16) - xx;
748             int c                  = ((xpos + xInc * 2) >> 16) - xx;
749             int d                  = ((xpos + xInc * 3) >> 16) - xx;
750             int inc                = (d + 1 < 4);
751             uint8_t *fragment      = (d + 1 < 4) ? fragmentB : fragmentA;
752             x86_reg imm8OfPShufW1  = (d + 1 < 4) ? imm8OfPShufW1B : imm8OfPShufW1A;
753             x86_reg imm8OfPShufW2  = (d + 1 < 4) ? imm8OfPShufW2B : imm8OfPShufW2A;
754             x86_reg fragmentLength = (d + 1 < 4) ? fragmentLengthB : fragmentLengthA;
755             int maxShift           = 3 - (d + inc);
756             int shift              = 0;
757
758             if (filterCode) {
759                 filter[i]        = ((xpos              & 0xFFFF) ^ 0xFFFF) >> 9;
760                 filter[i + 1]    = (((xpos + xInc)     & 0xFFFF) ^ 0xFFFF) >> 9;
761                 filter[i + 2]    = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
762                 filter[i + 3]    = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
763                 filterPos[i / 2] = xx;
764
765                 memcpy(filterCode + fragmentPos, fragment, fragmentLength);
766
767                 filterCode[fragmentPos + imm8OfPShufW1] =  (a + inc)       |
768                                                           ((b + inc) << 2) |
769                                                           ((c + inc) << 4) |
770                                                           ((d + inc) << 6);
771                 filterCode[fragmentPos + imm8OfPShufW2] =  a | (b << 2) |
772                                                                (c << 4) |
773                                                                (d << 6);
774
775                 if (i + 4 - inc >= dstW)
776                     shift = maxShift;               // avoid overread
777                 else if ((filterPos[i / 2] & 3) <= maxShift)
778                     shift = filterPos[i / 2] & 3;   // align
779
780                 if (shift && i >= shift) {
781                     filterCode[fragmentPos + imm8OfPShufW1] += 0x55 * shift;
782                     filterCode[fragmentPos + imm8OfPShufW2] += 0x55 * shift;
783                     filterPos[i / 2]                        -= shift;
784                 }
785             }
786
787             fragmentPos += fragmentLength;
788
789             if (filterCode)
790                 filterCode[fragmentPos] = RET;
791         }
792         xpos += xInc;
793     }
794     if (filterCode)
795         filterPos[((i / 2) + 1) & (~1)] = xpos >> 16;  // needed to jump to the next part
796
797     return fragmentPos + 1;
798 }
799 #endif /* HAVE_MMXEXT_INLINE */
800
801 static void getSubSampleFactors(int *h, int *v, enum AVPixelFormat format)
802 {
803     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
804     *h = desc->log2_chroma_w;
805     *v = desc->log2_chroma_h;
806 }
807
808 static void fill_rgb2yuv_table(SwsContext *c, const int table[4], int dstRange)
809 {
810     int64_t W, V, Z, Cy, Cu, Cv;
811     int64_t vr =  table[0];
812     int64_t ub =  table[1];
813     int64_t ug = -table[2];
814     int64_t vg = -table[3];
815     int64_t ONE = 65536;
816     int64_t cy = ONE;
817     uint8_t *p = (uint8_t*)c->input_rgb2yuv_table;
818     int i;
819     static const int8_t map[] = {
820     BY_IDX, GY_IDX, -1    , BY_IDX, BY_IDX, GY_IDX, -1    , BY_IDX,
821     RY_IDX, -1    , GY_IDX, RY_IDX, RY_IDX, -1    , GY_IDX, RY_IDX,
822     RY_IDX, GY_IDX, -1    , RY_IDX, RY_IDX, GY_IDX, -1    , RY_IDX,
823     BY_IDX, -1    , GY_IDX, BY_IDX, BY_IDX, -1    , GY_IDX, BY_IDX,
824     BU_IDX, GU_IDX, -1    , BU_IDX, BU_IDX, GU_IDX, -1    , BU_IDX,
825     RU_IDX, -1    , GU_IDX, RU_IDX, RU_IDX, -1    , GU_IDX, RU_IDX,
826     RU_IDX, GU_IDX, -1    , RU_IDX, RU_IDX, GU_IDX, -1    , RU_IDX,
827     BU_IDX, -1    , GU_IDX, BU_IDX, BU_IDX, -1    , GU_IDX, BU_IDX,
828     BV_IDX, GV_IDX, -1    , BV_IDX, BV_IDX, GV_IDX, -1    , BV_IDX,
829     RV_IDX, -1    , GV_IDX, RV_IDX, RV_IDX, -1    , GV_IDX, RV_IDX,
830     RV_IDX, GV_IDX, -1    , RV_IDX, RV_IDX, GV_IDX, -1    , RV_IDX,
831     BV_IDX, -1    , GV_IDX, BV_IDX, BV_IDX, -1    , GV_IDX, BV_IDX,
832     RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX,
833     BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX,
834     GY_IDX, -1    , GY_IDX, -1    , GY_IDX, -1    , GY_IDX, -1    ,
835     -1    , GY_IDX, -1    , GY_IDX, -1    , GY_IDX, -1    , GY_IDX,
836     RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX,
837     BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX,
838     GU_IDX, -1    , GU_IDX, -1    , GU_IDX, -1    , GU_IDX, -1    ,
839     -1    , GU_IDX, -1    , GU_IDX, -1    , GU_IDX, -1    , GU_IDX,
840     RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX,
841     BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX,
842     GV_IDX, -1    , GV_IDX, -1    , GV_IDX, -1    , GV_IDX, -1    ,
843     -1    , GV_IDX, -1    , GV_IDX, -1    , GV_IDX, -1    , GV_IDX, //23
844     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //24
845     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //25
846     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //26
847     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //27
848     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //28
849     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //29
850     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //30
851     -1    , -1    , -1    , -1    , -1    , -1    , -1    , -1    , //31
852     BY_IDX, GY_IDX, RY_IDX, -1    , -1    , -1    , -1    , -1    , //32
853     BU_IDX, GU_IDX, RU_IDX, -1    , -1    , -1    , -1    , -1    , //33
854     BV_IDX, GV_IDX, RV_IDX, -1    , -1    , -1    , -1    , -1    , //34
855     };
856
857     dstRange = 0; //FIXME range = 1 is handled elsewhere
858
859     if (!dstRange) {
860         cy = cy * 255 / 219;
861     } else {
862         vr = vr * 224 / 255;
863         ub = ub * 224 / 255;
864         ug = ug * 224 / 255;
865         vg = vg * 224 / 255;
866     }
867     W = ROUNDED_DIV(ONE*ONE*ug, ub);
868     V = ROUNDED_DIV(ONE*ONE*vg, vr);
869     Z = ONE*ONE-W-V;
870
871     Cy = ROUNDED_DIV(cy*Z, ONE);
872     Cu = ROUNDED_DIV(ub*Z, ONE);
873     Cv = ROUNDED_DIV(vr*Z, ONE);
874
875     c->input_rgb2yuv_table[RY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V        , Cy);
876     c->input_rgb2yuv_table[GY_IDX] =  ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE  , Cy);
877     c->input_rgb2yuv_table[BY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W        , Cy);
878
879     c->input_rgb2yuv_table[RU_IDX] =  ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V        , Cu);
880     c->input_rgb2yuv_table[GU_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE  , Cu);
881     c->input_rgb2yuv_table[BU_IDX] =  ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(Z+W)    , Cu);
882
883     c->input_rgb2yuv_table[RV_IDX] =  ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(V+Z)    , Cv);
884     c->input_rgb2yuv_table[GV_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE  , Cv);
885     c->input_rgb2yuv_table[BV_IDX] =  ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W        , Cv);
886
887     if(/*!dstRange && */table == ff_yuv2rgb_coeffs[SWS_CS_DEFAULT]) {
888         c->input_rgb2yuv_table[BY_IDX] =  ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
889         c->input_rgb2yuv_table[BV_IDX] = (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
890         c->input_rgb2yuv_table[BU_IDX] =  ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
891         c->input_rgb2yuv_table[GY_IDX] =  ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
892         c->input_rgb2yuv_table[GV_IDX] = (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
893         c->input_rgb2yuv_table[GU_IDX] = (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
894         c->input_rgb2yuv_table[RY_IDX] =  ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
895         c->input_rgb2yuv_table[RV_IDX] =  ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
896         c->input_rgb2yuv_table[RU_IDX] = (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
897     }
898     for(i=0; i<FF_ARRAY_ELEMS(map); i++)
899         AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
900 }
901
902 static void fill_xyztables(struct SwsContext *c)
903 {
904     int i;
905     double xyzgamma = XYZ_GAMMA;
906     double rgbgamma = 1.0 / RGB_GAMMA;
907     static const int16_t xyz2rgb_matrix[3][4] = {
908         {13270, -6295, -2041},
909         {-3969,  7682,   170},
910         {  228,  -835,  4329} };
911     static int16_t xyzgamma_tab[4096], rgbgamma_tab[4096];
912
913     memcpy(c->xyz2rgb_matrix, xyz2rgb_matrix, sizeof(c->xyz2rgb_matrix));
914     c->xyzgamma = xyzgamma_tab;
915     c->rgbgamma = rgbgamma_tab;
916
917     if (rgbgamma_tab[4095])
918         return;
919
920     /* set gamma vectors */
921     for (i = 0; i < 4096; i++) {
922         xyzgamma_tab[i] = lrint(pow(i / 4095.0, xyzgamma) * 4095.0);
923         rgbgamma_tab[i] = lrint(pow(i / 4095.0, rgbgamma) * 4095.0);
924     }
925 }
926
927 int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
928                              int srcRange, const int table[4], int dstRange,
929                              int brightness, int contrast, int saturation)
930 {
931     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
932     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
933     memcpy(c->srcColorspaceTable, inv_table, sizeof(int) * 4);
934     memcpy(c->dstColorspaceTable, table, sizeof(int) * 4);
935
936     if(!isYUV(c->dstFormat) && !isGray(c->dstFormat))
937         dstRange = 0;
938     if(!isYUV(c->srcFormat) && !isGray(c->srcFormat))
939         srcRange = 0;
940
941     c->brightness = brightness;
942     c->contrast   = contrast;
943     c->saturation = saturation;
944     c->srcRange   = srcRange;
945     c->dstRange   = dstRange;
946
947     fill_xyztables(c);
948
949     if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat)))
950         return -1;
951
952     c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
953     c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
954
955     if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) {
956     ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
957                              contrast, saturation);
958     // FIXME factorize
959
960     if (HAVE_ALTIVEC && av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)
961         ff_yuv2rgb_init_tables_altivec(c, inv_table, brightness,
962                                        contrast, saturation);
963     }
964
965     fill_rgb2yuv_table(c, table, dstRange);
966
967     return 0;
968 }
969
970 int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
971                              int *srcRange, int **table, int *dstRange,
972                              int *brightness, int *contrast, int *saturation)
973 {
974     if (!c || isYUV(c->dstFormat) || isGray(c->dstFormat))
975         return -1;
976
977     *inv_table  = c->srcColorspaceTable;
978     *table      = c->dstColorspaceTable;
979     *srcRange   = c->srcRange;
980     *dstRange   = c->dstRange;
981     *brightness = c->brightness;
982     *contrast   = c->contrast;
983     *saturation = c->saturation;
984
985     return 0;
986 }
987
988 static int handle_jpeg(enum AVPixelFormat *format)
989 {
990     switch (*format) {
991     case AV_PIX_FMT_YUVJ420P:
992         *format = AV_PIX_FMT_YUV420P;
993         return 1;
994     case AV_PIX_FMT_YUVJ422P:
995         *format = AV_PIX_FMT_YUV422P;
996         return 1;
997     case AV_PIX_FMT_YUVJ444P:
998         *format = AV_PIX_FMT_YUV444P;
999         return 1;
1000     case AV_PIX_FMT_YUVJ440P:
1001         *format = AV_PIX_FMT_YUV440P;
1002         return 1;
1003     default:
1004         return 0;
1005     }
1006 }
1007
1008 static int handle_0alpha(enum AVPixelFormat *format)
1009 {
1010     switch (*format) {
1011     case AV_PIX_FMT_0BGR    : *format = AV_PIX_FMT_ABGR   ; return 1;
1012     case AV_PIX_FMT_BGR0    : *format = AV_PIX_FMT_BGRA   ; return 4;
1013     case AV_PIX_FMT_0RGB    : *format = AV_PIX_FMT_ARGB   ; return 1;
1014     case AV_PIX_FMT_RGB0    : *format = AV_PIX_FMT_RGBA   ; return 4;
1015     default:                                          return 0;
1016     }
1017 }
1018
1019 static int handle_xyz(enum AVPixelFormat *format)
1020 {
1021     switch (*format) {
1022     case AV_PIX_FMT_XYZ12BE : *format = AV_PIX_FMT_RGB48BE; return 1;
1023     case AV_PIX_FMT_XYZ12LE : *format = AV_PIX_FMT_RGB48LE; return 1;
1024     default:                                                return 0;
1025     }
1026 }
1027
1028 SwsContext *sws_alloc_context(void)
1029 {
1030     SwsContext *c = av_mallocz(sizeof(SwsContext));
1031
1032     if (c) {
1033         c->av_class = &sws_context_class;
1034         av_opt_set_defaults(c);
1035     }
1036
1037     return c;
1038 }
1039
1040 av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
1041                              SwsFilter *dstFilter)
1042 {
1043     int i, j;
1044     int usesVFilter, usesHFilter;
1045     int unscaled;
1046     SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
1047     int srcW              = c->srcW;
1048     int srcH              = c->srcH;
1049     int dstW              = c->dstW;
1050     int dstH              = c->dstH;
1051     int dst_stride        = FFALIGN(dstW * sizeof(int16_t) + 66, 16);
1052     int flags, cpu_flags;
1053     enum AVPixelFormat srcFormat = c->srcFormat;
1054     enum AVPixelFormat dstFormat = c->dstFormat;
1055     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
1056     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
1057
1058     cpu_flags = av_get_cpu_flags();
1059     flags     = c->flags;
1060     emms_c();
1061     if (!rgb15to16)
1062         sws_rgb2rgb_init();
1063
1064     unscaled = (srcW == dstW && srcH == dstH);
1065
1066     handle_jpeg(&srcFormat);
1067     handle_jpeg(&dstFormat);
1068     if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat)
1069         av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
1070     handle_0alpha(&srcFormat);
1071     handle_0alpha(&dstFormat);
1072     handle_xyz(&srcFormat);
1073     handle_xyz(&dstFormat);
1074
1075     if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat){
1076         c->srcFormat= srcFormat;
1077         c->dstFormat= dstFormat;
1078     }
1079
1080     if (!sws_isSupportedInput(srcFormat)) {
1081         av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
1082                av_get_pix_fmt_name(srcFormat));
1083         return AVERROR(EINVAL);
1084     }
1085     if (!sws_isSupportedOutput(dstFormat)) {
1086         av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
1087                av_get_pix_fmt_name(dstFormat));
1088         return AVERROR(EINVAL);
1089     }
1090
1091     i = flags & (SWS_POINT         |
1092                  SWS_AREA          |
1093                  SWS_BILINEAR      |
1094                  SWS_FAST_BILINEAR |
1095                  SWS_BICUBIC       |
1096                  SWS_X             |
1097                  SWS_GAUSS         |
1098                  SWS_LANCZOS       |
1099                  SWS_SINC          |
1100                  SWS_SPLINE        |
1101                  SWS_BICUBLIN);
1102     if (!i || (i & (i - 1))) {
1103         av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen, got %X\n", i);
1104         return AVERROR(EINVAL);
1105     }
1106     /* sanity check */
1107     if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
1108         /* FIXME check if these are enough and try to lower them after
1109          * fixing the relevant parts of the code */
1110         av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
1111                srcW, srcH, dstW, dstH);
1112         return AVERROR(EINVAL);
1113     }
1114
1115     if (!dstFilter)
1116         dstFilter = &dummyFilter;
1117     if (!srcFilter)
1118         srcFilter = &dummyFilter;
1119
1120     c->lumXInc      = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
1121     c->lumYInc      = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
1122     c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
1123     c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
1124     c->vRounder     = 4 * 0x0001000100010001ULL;
1125
1126     usesVFilter = (srcFilter->lumV && srcFilter->lumV->length > 1) ||
1127                   (srcFilter->chrV && srcFilter->chrV->length > 1) ||
1128                   (dstFilter->lumV && dstFilter->lumV->length > 1) ||
1129                   (dstFilter->chrV && dstFilter->chrV->length > 1);
1130     usesHFilter = (srcFilter->lumH && srcFilter->lumH->length > 1) ||
1131                   (srcFilter->chrH && srcFilter->chrH->length > 1) ||
1132                   (dstFilter->lumH && dstFilter->lumH->length > 1) ||
1133                   (dstFilter->chrH && dstFilter->chrH->length > 1);
1134
1135     getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
1136     getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
1137
1138     if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
1139         if (dstW&1) {
1140             av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
1141             flags |= SWS_FULL_CHR_H_INT;
1142             c->flags = flags;
1143         }
1144     }
1145
1146     if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
1147        dstFormat == AV_PIX_FMT_RGB4_BYTE ||
1148        dstFormat == AV_PIX_FMT_BGR8 ||
1149        dstFormat == AV_PIX_FMT_RGB8) {
1150         if (flags & SWS_ERROR_DIFFUSION && !(flags & SWS_FULL_CHR_H_INT)) {
1151             av_log(c, AV_LOG_DEBUG,
1152                 "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n",
1153                 av_get_pix_fmt_name(dstFormat));
1154             flags   |= SWS_FULL_CHR_H_INT;
1155             c->flags = flags;
1156         }
1157         if (!(flags & SWS_ERROR_DIFFUSION) && (flags & SWS_FULL_CHR_H_INT)) {
1158             av_log(c, AV_LOG_DEBUG,
1159                 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
1160                 av_get_pix_fmt_name(dstFormat));
1161             flags   |= SWS_ERROR_DIFFUSION;
1162             c->flags = flags;
1163         }
1164     }
1165     if (isPlanarRGB(dstFormat)) {
1166         if (!(flags & SWS_FULL_CHR_H_INT)) {
1167             av_log(c, AV_LOG_DEBUG,
1168                    "%s output is not supported with half chroma resolution, switching to full\n",
1169                    av_get_pix_fmt_name(dstFormat));
1170             flags   |= SWS_FULL_CHR_H_INT;
1171             c->flags = flags;
1172         }
1173     }
1174
1175     /* reuse chroma for 2 pixels RGB/BGR unless user wants full
1176      * chroma interpolation */
1177     if (flags & SWS_FULL_CHR_H_INT &&
1178         isAnyRGB(dstFormat)        &&
1179         !isPlanarRGB(dstFormat)    &&
1180         dstFormat != AV_PIX_FMT_RGBA  &&
1181         dstFormat != AV_PIX_FMT_ARGB  &&
1182         dstFormat != AV_PIX_FMT_BGRA  &&
1183         dstFormat != AV_PIX_FMT_ABGR  &&
1184         dstFormat != AV_PIX_FMT_RGB24 &&
1185         dstFormat != AV_PIX_FMT_BGR24 &&
1186         dstFormat != AV_PIX_FMT_BGR4_BYTE &&
1187         dstFormat != AV_PIX_FMT_RGB4_BYTE &&
1188         dstFormat != AV_PIX_FMT_BGR8 &&
1189         dstFormat != AV_PIX_FMT_RGB8
1190     ) {
1191         av_log(c, AV_LOG_WARNING,
1192                "full chroma interpolation for destination format '%s' not yet implemented\n",
1193                av_get_pix_fmt_name(dstFormat));
1194         flags   &= ~SWS_FULL_CHR_H_INT;
1195         c->flags = flags;
1196     }
1197     if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
1198         c->chrDstHSubSample = 1;
1199
1200     // drop some chroma lines if the user wants it
1201     c->vChrDrop          = (flags & SWS_SRC_V_CHR_DROP_MASK) >>
1202                            SWS_SRC_V_CHR_DROP_SHIFT;
1203     c->chrSrcVSubSample += c->vChrDrop;
1204
1205     /* drop every other pixel for chroma calculation unless user
1206      * wants full chroma */
1207     if (isAnyRGB(srcFormat) && !(flags & SWS_FULL_CHR_H_INP)   &&
1208         srcFormat != AV_PIX_FMT_RGB8 && srcFormat != AV_PIX_FMT_BGR8 &&
1209         srcFormat != AV_PIX_FMT_RGB4 && srcFormat != AV_PIX_FMT_BGR4 &&
1210         srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
1211         srcFormat != AV_PIX_FMT_GBRP9BE   && srcFormat != AV_PIX_FMT_GBRP9LE  &&
1212         srcFormat != AV_PIX_FMT_GBRP10BE  && srcFormat != AV_PIX_FMT_GBRP10LE &&
1213         srcFormat != AV_PIX_FMT_GBRP12BE  && srcFormat != AV_PIX_FMT_GBRP12LE &&
1214         srcFormat != AV_PIX_FMT_GBRP14BE  && srcFormat != AV_PIX_FMT_GBRP14LE &&
1215         srcFormat != AV_PIX_FMT_GBRP16BE  && srcFormat != AV_PIX_FMT_GBRP16LE &&
1216         ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||
1217          (flags & SWS_FAST_BILINEAR)))
1218         c->chrSrcHSubSample = 1;
1219
1220     // Note the -((-x)>>y) is so that we always round toward +inf.
1221     c->chrSrcW = -((-srcW) >> c->chrSrcHSubSample);
1222     c->chrSrcH = -((-srcH) >> c->chrSrcVSubSample);
1223     c->chrDstW = -((-dstW) >> c->chrDstHSubSample);
1224     c->chrDstH = -((-dstH) >> c->chrDstVSubSample);
1225
1226     FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
1227
1228     /* unscaled special cases */
1229     if (unscaled && !usesHFilter && !usesVFilter &&
1230         (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
1231         ff_get_unscaled_swscale(c);
1232
1233         if (c->swScale) {
1234             if (flags & SWS_PRINT_INFO)
1235                 av_log(c, AV_LOG_INFO,
1236                        "using unscaled %s -> %s special converter\n",
1237                        av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
1238             return 0;
1239         }
1240     }
1241
1242     c->srcBpc = 1 + desc_src->comp[0].depth_minus1;
1243     if (c->srcBpc < 8)
1244         c->srcBpc = 8;
1245     c->dstBpc = 1 + desc_dst->comp[0].depth_minus1;
1246     if (c->dstBpc < 8)
1247         c->dstBpc = 8;
1248     if (isAnyRGB(srcFormat) || srcFormat == AV_PIX_FMT_PAL8)
1249         c->srcBpc = 16;
1250     if (c->dstBpc == 16)
1251         dst_stride <<= 1;
1252
1253     if (INLINE_MMXEXT(cpu_flags) && c->srcBpc == 8 && c->dstBpc <= 14) {
1254         c->canMMXEXTBeUsed = (dstW >= srcW && (dstW & 31) == 0 &&
1255                               (srcW & 15) == 0) ? 1 : 0;
1256         if (!c->canMMXEXTBeUsed && dstW >= srcW && (srcW & 15) == 0
1257
1258             && (flags & SWS_FAST_BILINEAR)) {
1259             if (flags & SWS_PRINT_INFO)
1260                 av_log(c, AV_LOG_INFO,
1261                        "output width is not a multiple of 32 -> no MMXEXT scaler\n");
1262         }
1263         if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat))
1264             c->canMMXEXTBeUsed = 0;
1265     } else
1266         c->canMMXEXTBeUsed = 0;
1267
1268     c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;
1269     c->chrYInc = (((int64_t)c->chrSrcH << 16) + (c->chrDstH >> 1)) / c->chrDstH;
1270
1271     /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
1272      * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
1273      * correct scaling.
1274      * n-2 is the last chrominance sample available.
1275      * This is not perfect, but no one should notice the difference, the more
1276      * correct variant would be like the vertical one, but that would require
1277      * some special code for the first and last pixel */
1278     if (flags & SWS_FAST_BILINEAR) {
1279         if (c->canMMXEXTBeUsed) {
1280             c->lumXInc += 20;
1281             c->chrXInc += 20;
1282         }
1283         // we don't use the x86 asm scaler if MMX is available
1284         else if (INLINE_MMX(cpu_flags) && c->dstBpc <= 14) {
1285             c->lumXInc = ((int64_t)(srcW       - 2) << 16) / (dstW       - 2) - 20;
1286             c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
1287         }
1288     }
1289
1290 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
1291
1292     /* precalculate horizontal scaler filter coefficients */
1293     {
1294 #if HAVE_MMXEXT_INLINE
1295 // can't downscale !!!
1296         if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
1297             c->lumMmxextFilterCodeSize = init_hscaler_mmxext(dstW, c->lumXInc, NULL,
1298                                                              NULL, NULL, 8);
1299             c->chrMmxextFilterCodeSize = init_hscaler_mmxext(c->chrDstW, c->chrXInc,
1300                                                              NULL, NULL, NULL, 4);
1301
1302 #if USE_MMAP
1303             c->lumMmxextFilterCode = mmap(NULL, c->lumMmxextFilterCodeSize,
1304                                           PROT_READ | PROT_WRITE,
1305                                           MAP_PRIVATE | MAP_ANONYMOUS,
1306                                           -1, 0);
1307             c->chrMmxextFilterCode = mmap(NULL, c->chrMmxextFilterCodeSize,
1308                                           PROT_READ | PROT_WRITE,
1309                                           MAP_PRIVATE | MAP_ANONYMOUS,
1310                                           -1, 0);
1311 #elif HAVE_VIRTUALALLOC
1312             c->lumMmxextFilterCode = VirtualAlloc(NULL,
1313                                                   c->lumMmxextFilterCodeSize,
1314                                                   MEM_COMMIT,
1315                                                   PAGE_EXECUTE_READWRITE);
1316             c->chrMmxextFilterCode = VirtualAlloc(NULL,
1317                                                   c->chrMmxextFilterCodeSize,
1318                                                   MEM_COMMIT,
1319                                                   PAGE_EXECUTE_READWRITE);
1320 #else
1321             c->lumMmxextFilterCode = av_malloc(c->lumMmxextFilterCodeSize);
1322             c->chrMmxextFilterCode = av_malloc(c->chrMmxextFilterCodeSize);
1323 #endif
1324
1325 #ifdef MAP_ANONYMOUS
1326             if (c->lumMmxextFilterCode == MAP_FAILED || c->chrMmxextFilterCode == MAP_FAILED)
1327 #else
1328             if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
1329 #endif
1330             {
1331                 av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
1332                 return AVERROR(ENOMEM);
1333             }
1334
1335             FF_ALLOCZ_OR_GOTO(c, c->hLumFilter,    (dstW           / 8 + 8) * sizeof(int16_t), fail);
1336             FF_ALLOCZ_OR_GOTO(c, c->hChrFilter,    (c->chrDstW     / 4 + 8) * sizeof(int16_t), fail);
1337             FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW       / 2 / 8 + 8) * sizeof(int32_t), fail);
1338             FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail);
1339
1340             init_hscaler_mmxext(      dstW, c->lumXInc, c->lumMmxextFilterCode,
1341                                 c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
1342             init_hscaler_mmxext(c->chrDstW, c->chrXInc, c->chrMmxextFilterCode,
1343                                 c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
1344
1345 #if USE_MMAP
1346             mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
1347             mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
1348 #endif
1349         } else
1350 #endif /* HAVE_MMXEXT_INLINE */
1351         {
1352             const int filterAlign =
1353                 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :
1354                 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
1355                 1;
1356
1357             if (initFilter(&c->hLumFilter, &c->hLumFilterPos,
1358                            &c->hLumFilterSize, c->lumXInc,
1359                            srcW, dstW, filterAlign, 1 << 14,
1360                            (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
1361                            cpu_flags, srcFilter->lumH, dstFilter->lumH,
1362                            c->param) < 0)
1363                 goto fail;
1364             if (initFilter(&c->hChrFilter, &c->hChrFilterPos,
1365                            &c->hChrFilterSize, c->chrXInc,
1366                            c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
1367                            (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
1368                            cpu_flags, srcFilter->chrH, dstFilter->chrH,
1369                            c->param) < 0)
1370                 goto fail;
1371         }
1372     } // initialize horizontal stuff
1373
1374     /* precalculate vertical scaler filter coefficients */
1375     {
1376         const int filterAlign =
1377             (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :
1378             (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
1379             1;
1380
1381         if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
1382                        c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
1383                        (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
1384                        cpu_flags, srcFilter->lumV, dstFilter->lumV,
1385                        c->param) < 0)
1386             goto fail;
1387         if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
1388                        c->chrYInc, c->chrSrcH, c->chrDstH,
1389                        filterAlign, (1 << 12),
1390                        (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
1391                        cpu_flags, srcFilter->chrV, dstFilter->chrV,
1392                        c->param) < 0)
1393             goto fail;
1394
1395 #if HAVE_ALTIVEC
1396         FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH,    fail);
1397         FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail);
1398
1399         for (i = 0; i < c->vLumFilterSize * c->dstH; i++) {
1400             int j;
1401             short *p = (short *)&c->vYCoeffsBank[i];
1402             for (j = 0; j < 8; j++)
1403                 p[j] = c->vLumFilter[i];
1404         }
1405
1406         for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {
1407             int j;
1408             short *p = (short *)&c->vCCoeffsBank[i];
1409             for (j = 0; j < 8; j++)
1410                 p[j] = c->vChrFilter[i];
1411         }
1412 #endif
1413     }
1414
1415     // calculate buffer sizes so that they won't run out while handling these damn slices
1416     c->vLumBufSize = c->vLumFilterSize;
1417     c->vChrBufSize = c->vChrFilterSize;
1418     for (i = 0; i < dstH; i++) {
1419         int chrI      = (int64_t)i * c->chrDstH / dstH;
1420         int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,
1421                               ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)
1422                                << c->chrSrcVSubSample));
1423
1424         nextSlice >>= c->chrSrcVSubSample;
1425         nextSlice <<= c->chrSrcVSubSample;
1426         if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)
1427             c->vLumBufSize = nextSlice - c->vLumFilterPos[i];
1428         if (c->vChrFilterPos[chrI] + c->vChrBufSize <
1429             (nextSlice >> c->chrSrcVSubSample))
1430             c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -
1431                              c->vChrFilterPos[chrI];
1432     }
1433
1434     for (i = 0; i < 4; i++)
1435         FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail);
1436
1437     /* Allocate pixbufs (we use dynamic allocation because otherwise we would
1438      * need to allocate several megabytes to handle all possible cases) */
1439     FF_ALLOC_OR_GOTO(c, c->lumPixBuf,  c->vLumBufSize * 3 * sizeof(int16_t *), fail);
1440     FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
1441     FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
1442     if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
1443         FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
1444     /* Note we need at least one pixel more at the end because of the MMX code
1445      * (just in case someone wants to replace the 4000/8000). */
1446     /* align at 16 bytes for AltiVec */
1447     for (i = 0; i < c->vLumBufSize; i++) {
1448         FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],
1449                           dst_stride + 16, fail);
1450         c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
1451     }
1452     // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
1453     c->uv_off   = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
1454     c->uv_offx2 = dst_stride + 16;
1455     for (i = 0; i < c->vChrBufSize; i++) {
1456         FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
1457                          dst_stride * 2 + 32, fail);
1458         c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
1459         c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
1460                          = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
1461     }
1462     if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1463         for (i = 0; i < c->vLumBufSize; i++) {
1464             FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],
1465                               dst_stride + 16, fail);
1466             c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];
1467         }
1468
1469     // try to avoid drawing green stuff between the right end and the stride end
1470     for (i = 0; i < c->vChrBufSize; i++)
1471         if(desc_dst->comp[0].depth_minus1 == 15){
1472             av_assert0(c->dstBpc > 14);
1473             for(j=0; j<dst_stride/2+1; j++)
1474                 ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
1475         } else
1476             for(j=0; j<dst_stride+1; j++)
1477                 ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
1478
1479     av_assert0(c->chrDstH <= dstH);
1480
1481     if (flags & SWS_PRINT_INFO) {
1482         if (flags & SWS_FAST_BILINEAR)
1483             av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");
1484         else if (flags & SWS_BILINEAR)
1485             av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");
1486         else if (flags & SWS_BICUBIC)
1487             av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");
1488         else if (flags & SWS_X)
1489             av_log(c, AV_LOG_INFO, "Experimental scaler, ");
1490         else if (flags & SWS_POINT)
1491             av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");
1492         else if (flags & SWS_AREA)
1493             av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");
1494         else if (flags & SWS_BICUBLIN)
1495             av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");
1496         else if (flags & SWS_GAUSS)
1497             av_log(c, AV_LOG_INFO, "Gaussian scaler, ");
1498         else if (flags & SWS_SINC)
1499             av_log(c, AV_LOG_INFO, "Sinc scaler, ");
1500         else if (flags & SWS_LANCZOS)
1501             av_log(c, AV_LOG_INFO, "Lanczos scaler, ");
1502         else if (flags & SWS_SPLINE)
1503             av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");
1504         else
1505             av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");
1506
1507         av_log(c, AV_LOG_INFO, "from %s to %s%s ",
1508                av_get_pix_fmt_name(srcFormat),
1509 #ifdef DITHER1XBPP
1510                dstFormat == AV_PIX_FMT_BGR555   || dstFormat == AV_PIX_FMT_BGR565   ||
1511                dstFormat == AV_PIX_FMT_RGB444BE || dstFormat == AV_PIX_FMT_RGB444LE ||
1512                dstFormat == AV_PIX_FMT_BGR444BE || dstFormat == AV_PIX_FMT_BGR444LE ?
1513                                                              "dithered " : "",
1514 #else
1515                "",
1516 #endif
1517                av_get_pix_fmt_name(dstFormat));
1518
1519         if (INLINE_MMXEXT(cpu_flags))
1520             av_log(c, AV_LOG_INFO, "using MMXEXT\n");
1521         else if (INLINE_AMD3DNOW(cpu_flags))
1522             av_log(c, AV_LOG_INFO, "using 3DNOW\n");
1523         else if (INLINE_MMX(cpu_flags))
1524             av_log(c, AV_LOG_INFO, "using MMX\n");
1525         else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC)
1526             av_log(c, AV_LOG_INFO, "using AltiVec\n");
1527         else
1528             av_log(c, AV_LOG_INFO, "using C\n");
1529
1530         av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
1531         av_log(c, AV_LOG_DEBUG,
1532                "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1533                c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
1534         av_log(c, AV_LOG_DEBUG,
1535                "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1536                c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
1537                c->chrXInc, c->chrYInc);
1538     }
1539
1540     c->swScale = ff_getSwsFunc(c);
1541     return 0;
1542 fail: // FIXME replace things by appropriate error codes
1543     return -1;
1544 }
1545
1546 #if FF_API_SWS_GETCONTEXT
1547 SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
1548                            int dstW, int dstH, enum AVPixelFormat dstFormat,
1549                            int flags, SwsFilter *srcFilter,
1550                            SwsFilter *dstFilter, const double *param)
1551 {
1552     SwsContext *c;
1553
1554     if (!(c = sws_alloc_context()))
1555         return NULL;
1556
1557     c->flags     = flags;
1558     c->srcW      = srcW;
1559     c->srcH      = srcH;
1560     c->dstW      = dstW;
1561     c->dstH      = dstH;
1562     c->srcRange  = handle_jpeg(&srcFormat);
1563     c->dstRange  = handle_jpeg(&dstFormat);
1564     c->src0Alpha = handle_0alpha(&srcFormat);
1565     c->dst0Alpha = handle_0alpha(&dstFormat);
1566     c->srcXYZ    = handle_xyz(&srcFormat);
1567     c->dstXYZ    = handle_xyz(&dstFormat);
1568     c->srcFormat = srcFormat;
1569     c->dstFormat = dstFormat;
1570
1571     if (param) {
1572         c->param[0] = param[0];
1573         c->param[1] = param[1];
1574     }
1575     sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
1576                              ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
1577                              c->dstRange, 0, 1 << 16, 1 << 16);
1578
1579     if (sws_init_context(c, srcFilter, dstFilter) < 0) {
1580         sws_freeContext(c);
1581         return NULL;
1582     }
1583
1584     return c;
1585 }
1586 #endif
1587
1588 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
1589                                 float lumaSharpen, float chromaSharpen,
1590                                 float chromaHShift, float chromaVShift,
1591                                 int verbose)
1592 {
1593     SwsFilter *filter = av_malloc(sizeof(SwsFilter));
1594     if (!filter)
1595         return NULL;
1596
1597     if (lumaGBlur != 0.0) {
1598         filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
1599         filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
1600     } else {
1601         filter->lumH = sws_getIdentityVec();
1602         filter->lumV = sws_getIdentityVec();
1603     }
1604
1605     if (chromaGBlur != 0.0) {
1606         filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
1607         filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
1608     } else {
1609         filter->chrH = sws_getIdentityVec();
1610         filter->chrV = sws_getIdentityVec();
1611     }
1612
1613     if (chromaSharpen != 0.0) {
1614         SwsVector *id = sws_getIdentityVec();
1615         sws_scaleVec(filter->chrH, -chromaSharpen);
1616         sws_scaleVec(filter->chrV, -chromaSharpen);
1617         sws_addVec(filter->chrH, id);
1618         sws_addVec(filter->chrV, id);
1619         sws_freeVec(id);
1620     }
1621
1622     if (lumaSharpen != 0.0) {
1623         SwsVector *id = sws_getIdentityVec();
1624         sws_scaleVec(filter->lumH, -lumaSharpen);
1625         sws_scaleVec(filter->lumV, -lumaSharpen);
1626         sws_addVec(filter->lumH, id);
1627         sws_addVec(filter->lumV, id);
1628         sws_freeVec(id);
1629     }
1630
1631     if (chromaHShift != 0.0)
1632         sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
1633
1634     if (chromaVShift != 0.0)
1635         sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
1636
1637     sws_normalizeVec(filter->chrH, 1.0);
1638     sws_normalizeVec(filter->chrV, 1.0);
1639     sws_normalizeVec(filter->lumH, 1.0);
1640     sws_normalizeVec(filter->lumV, 1.0);
1641
1642     if (verbose)
1643         sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
1644     if (verbose)
1645         sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
1646
1647     return filter;
1648 }
1649
1650 SwsVector *sws_allocVec(int length)
1651 {
1652     SwsVector *vec;
1653
1654     if(length <= 0 || length > INT_MAX/ sizeof(double))
1655         return NULL;
1656
1657     vec = av_malloc(sizeof(SwsVector));
1658     if (!vec)
1659         return NULL;
1660     vec->length = length;
1661     vec->coeff  = av_malloc(sizeof(double) * length);
1662     if (!vec->coeff)
1663         av_freep(&vec);
1664     return vec;
1665 }
1666
1667 SwsVector *sws_getGaussianVec(double variance, double quality)
1668 {
1669     const int length = (int)(variance * quality + 0.5) | 1;
1670     int i;
1671     double middle  = (length - 1) * 0.5;
1672     SwsVector *vec;
1673
1674     if(variance < 0 || quality < 0)
1675         return NULL;
1676
1677     vec = sws_allocVec(length);
1678
1679     if (!vec)
1680         return NULL;
1681
1682     for (i = 0; i < length; i++) {
1683         double dist = i - middle;
1684         vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
1685                         sqrt(2 * variance * M_PI);
1686     }
1687
1688     sws_normalizeVec(vec, 1.0);
1689
1690     return vec;
1691 }
1692
1693 SwsVector *sws_getConstVec(double c, int length)
1694 {
1695     int i;
1696     SwsVector *vec = sws_allocVec(length);
1697
1698     if (!vec)
1699         return NULL;
1700
1701     for (i = 0; i < length; i++)
1702         vec->coeff[i] = c;
1703
1704     return vec;
1705 }
1706
1707 SwsVector *sws_getIdentityVec(void)
1708 {
1709     return sws_getConstVec(1.0, 1);
1710 }
1711
1712 static double sws_dcVec(SwsVector *a)
1713 {
1714     int i;
1715     double sum = 0;
1716
1717     for (i = 0; i < a->length; i++)
1718         sum += a->coeff[i];
1719
1720     return sum;
1721 }
1722
1723 void sws_scaleVec(SwsVector *a, double scalar)
1724 {
1725     int i;
1726
1727     for (i = 0; i < a->length; i++)
1728         a->coeff[i] *= scalar;
1729 }
1730
1731 void sws_normalizeVec(SwsVector *a, double height)
1732 {
1733     sws_scaleVec(a, height / sws_dcVec(a));
1734 }
1735
1736 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
1737 {
1738     int length = a->length + b->length - 1;
1739     int i, j;
1740     SwsVector *vec = sws_getConstVec(0.0, length);
1741
1742     if (!vec)
1743         return NULL;
1744
1745     for (i = 0; i < a->length; i++) {
1746         for (j = 0; j < b->length; j++) {
1747             vec->coeff[i + j] += a->coeff[i] * b->coeff[j];
1748         }
1749     }
1750
1751     return vec;
1752 }
1753
1754 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
1755 {
1756     int length = FFMAX(a->length, b->length);
1757     int i;
1758     SwsVector *vec = sws_getConstVec(0.0, length);
1759
1760     if (!vec)
1761         return NULL;
1762
1763     for (i = 0; i < a->length; i++)
1764         vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
1765     for (i = 0; i < b->length; i++)
1766         vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
1767
1768     return vec;
1769 }
1770
1771 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
1772 {
1773     int length = FFMAX(a->length, b->length);
1774     int i;
1775     SwsVector *vec = sws_getConstVec(0.0, length);
1776
1777     if (!vec)
1778         return NULL;
1779
1780     for (i = 0; i < a->length; i++)
1781         vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
1782     for (i = 0; i < b->length; i++)
1783         vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] -= b->coeff[i];
1784
1785     return vec;
1786 }
1787
1788 /* shift left / or right if "shift" is negative */
1789 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
1790 {
1791     int length = a->length + FFABS(shift) * 2;
1792     int i;
1793     SwsVector *vec = sws_getConstVec(0.0, length);
1794
1795     if (!vec)
1796         return NULL;
1797
1798     for (i = 0; i < a->length; i++) {
1799         vec->coeff[i + (length    - 1) / 2 -
1800                        (a->length - 1) / 2 - shift] = a->coeff[i];
1801     }
1802
1803     return vec;
1804 }
1805
1806 void sws_shiftVec(SwsVector *a, int shift)
1807 {
1808     SwsVector *shifted = sws_getShiftedVec(a, shift);
1809     av_free(a->coeff);
1810     a->coeff  = shifted->coeff;
1811     a->length = shifted->length;
1812     av_free(shifted);
1813 }
1814
1815 void sws_addVec(SwsVector *a, SwsVector *b)
1816 {
1817     SwsVector *sum = sws_sumVec(a, b);
1818     av_free(a->coeff);
1819     a->coeff  = sum->coeff;
1820     a->length = sum->length;
1821     av_free(sum);
1822 }
1823
1824 void sws_subVec(SwsVector *a, SwsVector *b)
1825 {
1826     SwsVector *diff = sws_diffVec(a, b);
1827     av_free(a->coeff);
1828     a->coeff  = diff->coeff;
1829     a->length = diff->length;
1830     av_free(diff);
1831 }
1832
1833 void sws_convVec(SwsVector *a, SwsVector *b)
1834 {
1835     SwsVector *conv = sws_getConvVec(a, b);
1836     av_free(a->coeff);
1837     a->coeff  = conv->coeff;
1838     a->length = conv->length;
1839     av_free(conv);
1840 }
1841
1842 SwsVector *sws_cloneVec(SwsVector *a)
1843 {
1844     int i;
1845     SwsVector *vec = sws_allocVec(a->length);
1846
1847     if (!vec)
1848         return NULL;
1849
1850     for (i = 0; i < a->length; i++)
1851         vec->coeff[i] = a->coeff[i];
1852
1853     return vec;
1854 }
1855
1856 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
1857 {
1858     int i;
1859     double max = 0;
1860     double min = 0;
1861     double range;
1862
1863     for (i = 0; i < a->length; i++)
1864         if (a->coeff[i] > max)
1865             max = a->coeff[i];
1866
1867     for (i = 0; i < a->length; i++)
1868         if (a->coeff[i] < min)
1869             min = a->coeff[i];
1870
1871     range = max - min;
1872
1873     for (i = 0; i < a->length; i++) {
1874         int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
1875         av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
1876         for (; x > 0; x--)
1877             av_log(log_ctx, log_level, " ");
1878         av_log(log_ctx, log_level, "|\n");
1879     }
1880 }
1881
1882 void sws_freeVec(SwsVector *a)
1883 {
1884     if (!a)
1885         return;
1886     av_freep(&a->coeff);
1887     a->length = 0;
1888     av_free(a);
1889 }
1890
1891 void sws_freeFilter(SwsFilter *filter)
1892 {
1893     if (!filter)
1894         return;
1895
1896     if (filter->lumH)
1897         sws_freeVec(filter->lumH);
1898     if (filter->lumV)
1899         sws_freeVec(filter->lumV);
1900     if (filter->chrH)
1901         sws_freeVec(filter->chrH);
1902     if (filter->chrV)
1903         sws_freeVec(filter->chrV);
1904     av_free(filter);
1905 }
1906
1907 void sws_freeContext(SwsContext *c)
1908 {
1909     int i;
1910     if (!c)
1911         return;
1912
1913     if (c->lumPixBuf) {
1914         for (i = 0; i < c->vLumBufSize; i++)
1915             av_freep(&c->lumPixBuf[i]);
1916         av_freep(&c->lumPixBuf);
1917     }
1918
1919     if (c->chrUPixBuf) {
1920         for (i = 0; i < c->vChrBufSize; i++)
1921             av_freep(&c->chrUPixBuf[i]);
1922         av_freep(&c->chrUPixBuf);
1923         av_freep(&c->chrVPixBuf);
1924     }
1925
1926     if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
1927         for (i = 0; i < c->vLumBufSize; i++)
1928             av_freep(&c->alpPixBuf[i]);
1929         av_freep(&c->alpPixBuf);
1930     }
1931
1932     for (i = 0; i < 4; i++)
1933         av_freep(&c->dither_error[i]);
1934
1935     av_freep(&c->vLumFilter);
1936     av_freep(&c->vChrFilter);
1937     av_freep(&c->hLumFilter);
1938     av_freep(&c->hChrFilter);
1939 #if HAVE_ALTIVEC
1940     av_freep(&c->vYCoeffsBank);
1941     av_freep(&c->vCCoeffsBank);
1942 #endif
1943
1944     av_freep(&c->vLumFilterPos);
1945     av_freep(&c->vChrFilterPos);
1946     av_freep(&c->hLumFilterPos);
1947     av_freep(&c->hChrFilterPos);
1948
1949 #if HAVE_MMX_INLINE
1950 #if USE_MMAP
1951     if (c->lumMmxextFilterCode)
1952         munmap(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize);
1953     if (c->chrMmxextFilterCode)
1954         munmap(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize);
1955 #elif HAVE_VIRTUALALLOC
1956     if (c->lumMmxextFilterCode)
1957         VirtualFree(c->lumMmxextFilterCode, 0, MEM_RELEASE);
1958     if (c->chrMmxextFilterCode)
1959         VirtualFree(c->chrMmxextFilterCode, 0, MEM_RELEASE);
1960 #else
1961     av_free(c->lumMmxextFilterCode);
1962     av_free(c->chrMmxextFilterCode);
1963 #endif
1964     c->lumMmxextFilterCode = NULL;
1965     c->chrMmxextFilterCode = NULL;
1966 #endif /* HAVE_MMX_INLINE */
1967
1968     av_freep(&c->yuvTable);
1969     av_freep(&c->formatConvBuffer);
1970
1971     av_free(c);
1972 }
1973
1974 struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
1975                                         int srcH, enum AVPixelFormat srcFormat,
1976                                         int dstW, int dstH,
1977                                         enum AVPixelFormat dstFormat, int flags,
1978                                         SwsFilter *srcFilter,
1979                                         SwsFilter *dstFilter,
1980                                         const double *param)
1981 {
1982     static const double default_param[2] = { SWS_PARAM_DEFAULT,
1983                                              SWS_PARAM_DEFAULT };
1984
1985     if (!param)
1986         param = default_param;
1987
1988     if (context &&
1989         (context->srcW      != srcW      ||
1990          context->srcH      != srcH      ||
1991          context->srcFormat != srcFormat ||
1992          context->dstW      != dstW      ||
1993          context->dstH      != dstH      ||
1994          context->dstFormat != dstFormat ||
1995          context->flags     != flags     ||
1996          context->param[0]  != param[0]  ||
1997          context->param[1]  != param[1])) {
1998         sws_freeContext(context);
1999         context = NULL;
2000     }
2001
2002     if (!context) {
2003         if (!(context = sws_alloc_context()))
2004             return NULL;
2005         context->srcW      = srcW;
2006         context->srcH      = srcH;
2007         context->srcRange  = handle_jpeg(&srcFormat);
2008         context->src0Alpha = handle_0alpha(&srcFormat);
2009         context->srcXYZ    = handle_xyz(&srcFormat);
2010         context->srcFormat = srcFormat;
2011         context->dstW      = dstW;
2012         context->dstH      = dstH;
2013         context->dstRange  = handle_jpeg(&dstFormat);
2014         context->dst0Alpha = handle_0alpha(&dstFormat);
2015         context->dstXYZ    = handle_xyz(&dstFormat);
2016         context->dstFormat = dstFormat;
2017         context->flags     = flags;
2018         context->param[0]  = param[0];
2019         context->param[1]  = param[1];
2020         sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
2021                                  context->srcRange,
2022                                  ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
2023                                  context->dstRange, 0, 1 << 16, 1 << 16);
2024         if (sws_init_context(context, srcFilter, dstFilter) < 0) {
2025             sws_freeContext(context);
2026             return NULL;
2027         }
2028     }
2029     return context;
2030 }