2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
4 * This file is part of Libav.
6 * Libav 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.
11 * Libav 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
32 #define MAP_ANONYMOUS MAP_ANON
36 #define WIN32_LEAN_AND_MEAN
40 #include "libavutil/attributes.h"
41 #include "libavutil/avutil.h"
42 #include "libavutil/bswap.h"
43 #include "libavutil/cpu.h"
44 #include "libavutil/intreadwrite.h"
45 #include "libavutil/mathematics.h"
46 #include "libavutil/opt.h"
47 #include "libavutil/pixdesc.h"
48 #include "libavutil/ppc/cpu.h"
49 #include "libavutil/x86/asm.h"
50 #include "libavutil/x86/cpu.h"
53 #include "swscale_internal.h"
55 unsigned swscale_version(void)
57 return LIBSWSCALE_VERSION_INT
;
60 const char *swscale_configuration(void)
62 return LIBAV_CONFIGURATION
;
65 const char *swscale_license(void)
67 #define LICENSE_PREFIX "libswscale license: "
68 return LICENSE_PREFIX LIBAV_LICENSE
+ sizeof(LICENSE_PREFIX
) - 1;
71 #define RET 0xC3 // near return opcode for x86
73 typedef struct FormatEntry
{
74 uint8_t is_supported_in
:1;
75 uint8_t is_supported_out
:1;
76 uint8_t is_supported_endianness
:1;
79 static const FormatEntry format_entries
[AV_PIX_FMT_NB
] = {
80 [AV_PIX_FMT_YUV420P
] = { 1, 1 },
81 [AV_PIX_FMT_YUYV422
] = { 1, 1 },
82 [AV_PIX_FMT_RGB24
] = { 1, 1 },
83 [AV_PIX_FMT_BGR24
] = { 1, 1 },
84 [AV_PIX_FMT_YUV422P
] = { 1, 1 },
85 [AV_PIX_FMT_YUV444P
] = { 1, 1 },
86 [AV_PIX_FMT_YUV410P
] = { 1, 1 },
87 [AV_PIX_FMT_YUV411P
] = { 1, 1 },
88 [AV_PIX_FMT_GRAY8
] = { 1, 1 },
89 [AV_PIX_FMT_MONOWHITE
] = { 1, 1 },
90 [AV_PIX_FMT_MONOBLACK
] = { 1, 1 },
91 [AV_PIX_FMT_PAL8
] = { 1, 0 },
92 [AV_PIX_FMT_YUVJ420P
] = { 1, 1 },
93 [AV_PIX_FMT_YUVJ422P
] = { 1, 1 },
94 [AV_PIX_FMT_YUVJ444P
] = { 1, 1 },
95 [AV_PIX_FMT_UYVY422
] = { 1, 1 },
96 [AV_PIX_FMT_UYYVYY411
] = { 0, 0 },
97 [AV_PIX_FMT_BGR8
] = { 1, 1 },
98 [AV_PIX_FMT_BGR4
] = { 0, 1 },
99 [AV_PIX_FMT_BGR4_BYTE
] = { 1, 1 },
100 [AV_PIX_FMT_RGB8
] = { 1, 1 },
101 [AV_PIX_FMT_RGB4
] = { 0, 1 },
102 [AV_PIX_FMT_RGB4_BYTE
] = { 1, 1 },
103 [AV_PIX_FMT_NV12
] = { 1, 1 },
104 [AV_PIX_FMT_NV21
] = { 1, 1 },
105 [AV_PIX_FMT_ARGB
] = { 1, 1 },
106 [AV_PIX_FMT_RGBA
] = { 1, 1 },
107 [AV_PIX_FMT_ABGR
] = { 1, 1 },
108 [AV_PIX_FMT_BGRA
] = { 1, 1 },
109 [AV_PIX_FMT_GRAY16BE
] = { 1, 1 },
110 [AV_PIX_FMT_GRAY16LE
] = { 1, 1 },
111 [AV_PIX_FMT_YUV440P
] = { 1, 1 },
112 [AV_PIX_FMT_YUVJ440P
] = { 1, 1 },
113 [AV_PIX_FMT_YUVA420P
] = { 1, 1 },
114 [AV_PIX_FMT_YUVA422P
] = { 1, 1 },
115 [AV_PIX_FMT_YUVA444P
] = { 1, 1 },
116 [AV_PIX_FMT_YUVA420P9BE
] = { 1, 1 },
117 [AV_PIX_FMT_YUVA420P9LE
] = { 1, 1 },
118 [AV_PIX_FMT_YUVA422P9BE
] = { 1, 1 },
119 [AV_PIX_FMT_YUVA422P9LE
] = { 1, 1 },
120 [AV_PIX_FMT_YUVA444P9BE
] = { 1, 1 },
121 [AV_PIX_FMT_YUVA444P9LE
] = { 1, 1 },
122 [AV_PIX_FMT_YUVA420P10BE
]= { 1, 1 },
123 [AV_PIX_FMT_YUVA420P10LE
]= { 1, 1 },
124 [AV_PIX_FMT_YUVA422P10BE
]= { 1, 1 },
125 [AV_PIX_FMT_YUVA422P10LE
]= { 1, 1 },
126 [AV_PIX_FMT_YUVA444P10BE
]= { 1, 1 },
127 [AV_PIX_FMT_YUVA444P10LE
]= { 1, 1 },
128 [AV_PIX_FMT_YUVA420P16BE
]= { 1, 1 },
129 [AV_PIX_FMT_YUVA420P16LE
]= { 1, 1 },
130 [AV_PIX_FMT_YUVA422P16BE
]= { 1, 1 },
131 [AV_PIX_FMT_YUVA422P16LE
]= { 1, 1 },
132 [AV_PIX_FMT_YUVA444P16BE
]= { 1, 1 },
133 [AV_PIX_FMT_YUVA444P16LE
]= { 1, 1 },
134 [AV_PIX_FMT_RGB48BE
] = { 1, 1 },
135 [AV_PIX_FMT_RGB48LE
] = { 1, 1 },
136 [AV_PIX_FMT_RGB565BE
] = { 1, 1 },
137 [AV_PIX_FMT_RGB565LE
] = { 1, 1 },
138 [AV_PIX_FMT_RGB555BE
] = { 1, 1 },
139 [AV_PIX_FMT_RGB555LE
] = { 1, 1 },
140 [AV_PIX_FMT_BGR565BE
] = { 1, 1 },
141 [AV_PIX_FMT_BGR565LE
] = { 1, 1 },
142 [AV_PIX_FMT_BGR555BE
] = { 1, 1 },
143 [AV_PIX_FMT_BGR555LE
] = { 1, 1 },
144 [AV_PIX_FMT_YUV420P16LE
] = { 1, 1 },
145 [AV_PIX_FMT_YUV420P16BE
] = { 1, 1 },
146 [AV_PIX_FMT_YUV422P16LE
] = { 1, 1 },
147 [AV_PIX_FMT_YUV422P16BE
] = { 1, 1 },
148 [AV_PIX_FMT_YUV444P16LE
] = { 1, 1 },
149 [AV_PIX_FMT_YUV444P16BE
] = { 1, 1 },
150 [AV_PIX_FMT_RGB444LE
] = { 1, 1 },
151 [AV_PIX_FMT_RGB444BE
] = { 1, 1 },
152 [AV_PIX_FMT_BGR444LE
] = { 1, 1 },
153 [AV_PIX_FMT_BGR444BE
] = { 1, 1 },
154 [AV_PIX_FMT_Y400A
] = { 1, 0 },
155 [AV_PIX_FMT_BGR48BE
] = { 1, 1 },
156 [AV_PIX_FMT_BGR48LE
] = { 1, 1 },
157 [AV_PIX_FMT_YUV420P9BE
] = { 1, 1 },
158 [AV_PIX_FMT_YUV420P9LE
] = { 1, 1 },
159 [AV_PIX_FMT_YUV420P10BE
] = { 1, 1 },
160 [AV_PIX_FMT_YUV420P10LE
] = { 1, 1 },
161 [AV_PIX_FMT_YUV422P9BE
] = { 1, 1 },
162 [AV_PIX_FMT_YUV422P9LE
] = { 1, 1 },
163 [AV_PIX_FMT_YUV422P10BE
] = { 1, 1 },
164 [AV_PIX_FMT_YUV422P10LE
] = { 1, 1 },
165 [AV_PIX_FMT_YUV444P9BE
] = { 1, 1 },
166 [AV_PIX_FMT_YUV444P9LE
] = { 1, 1 },
167 [AV_PIX_FMT_YUV444P10BE
] = { 1, 1 },
168 [AV_PIX_FMT_YUV444P10LE
] = { 1, 1 },
169 [AV_PIX_FMT_GBRP
] = { 1, 1 },
170 [AV_PIX_FMT_GBRP9LE
] = { 1, 1 },
171 [AV_PIX_FMT_GBRP9BE
] = { 1, 1 },
172 [AV_PIX_FMT_GBRP10LE
] = { 1, 1 },
173 [AV_PIX_FMT_GBRP10BE
] = { 1, 1 },
174 [AV_PIX_FMT_GBRP16LE
] = { 1, 0 },
175 [AV_PIX_FMT_GBRP16BE
] = { 1, 0 },
176 [AV_PIX_FMT_XYZ12BE
] = { 0, 0, 1 },
177 [AV_PIX_FMT_XYZ12LE
] = { 0, 0, 1 },
180 int sws_isSupportedInput(enum AVPixelFormat pix_fmt
)
182 return (unsigned)pix_fmt
< AV_PIX_FMT_NB ?
183 format_entries
[pix_fmt
].is_supported_in
: 0;
186 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt
)
188 return (unsigned)pix_fmt
< AV_PIX_FMT_NB ?
189 format_entries
[pix_fmt
].is_supported_out
: 0;
192 int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt
)
194 return (unsigned)pix_fmt
< AV_PIX_FMT_NB ?
195 format_entries
[pix_fmt
].is_supported_endianness
: 0;
198 const char *sws_format_name(enum AVPixelFormat format
)
200 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(format
);
204 return "Unknown format";
207 static double getSplineCoeff(double a
, double b
, double c
, double d
,
211 return ((d
* dist
+ c
) * dist
+ b
) * dist
+ a
;
213 return getSplineCoeff(0.0,
214 b
+ 2.0 * c
+ 3.0 * d
,
216 -b
- 3.0 * c
- 6.0 * d
,
220 static av_cold
int initFilter(int16_t **outFilter
, int32_t **filterPos
,
221 int *outFilterSize
, int xInc
, int srcW
,
222 int dstW
, int filterAlign
, int one
,
223 int flags
, int cpu_flags
,
224 SwsVector
*srcFilter
, SwsVector
*dstFilter
,
225 double param
[2], int is_horizontal
)
231 int64_t *filter
= NULL
;
232 int64_t *filter2
= NULL
;
233 const int64_t fone
= 1LL << 54;
236 emms_c(); // FIXME should not be required but IS (even for non-MMX versions)
238 // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
239 FF_ALLOC_OR_GOTO(NULL
, *filterPos
, (dstW
+ 3) * sizeof(**filterPos
), fail
);
241 if (FFABS(xInc
- 0x10000) < 10) { // unscaled
244 FF_ALLOCZ_OR_GOTO(NULL
, filter
,
245 dstW
* sizeof(*filter
) * filterSize
, fail
);
247 for (i
= 0; i
< dstW
; i
++) {
248 filter
[i
* filterSize
] = fone
;
251 } else if (flags
& SWS_POINT
) { // lame looking point sampling mode
255 FF_ALLOC_OR_GOTO(NULL
, filter
,
256 dstW
* sizeof(*filter
) * filterSize
, fail
);
258 xDstInSrc
= xInc
/ 2 - 0x8000;
259 for (i
= 0; i
< dstW
; i
++) {
260 int xx
= (xDstInSrc
- ((filterSize
- 1) << 15) + (1 << 15)) >> 16;
262 (*filterPos
)[i
] = xx
;
266 } else if ((xInc
<= (1 << 16) && (flags
& SWS_AREA
)) ||
267 (flags
& SWS_FAST_BILINEAR
)) { // bilinear upscale
271 FF_ALLOC_OR_GOTO(NULL
, filter
,
272 dstW
* sizeof(*filter
) * filterSize
, fail
);
274 xDstInSrc
= xInc
/ 2 - 0x8000;
275 for (i
= 0; i
< dstW
; i
++) {
276 int xx
= (xDstInSrc
- ((filterSize
- 1) << 15) + (1 << 15)) >> 16;
279 (*filterPos
)[i
] = xx
;
280 // bilinear upscale / linear interpolate / area averaging
281 for (j
= 0; j
< filterSize
; j
++) {
282 int64_t coeff
= fone
- FFABS((xx
<< 16) - xDstInSrc
) *
286 filter
[i
* filterSize
+ j
] = coeff
;
295 if (flags
& SWS_BICUBIC
)
297 else if (flags
& SWS_X
)
299 else if (flags
& SWS_AREA
)
300 sizeFactor
= 1; // downscale only, for upscale it is bilinear
301 else if (flags
& SWS_GAUSS
)
302 sizeFactor
= 8; // infinite ;)
303 else if (flags
& SWS_LANCZOS
)
304 sizeFactor
= param
[0] != SWS_PARAM_DEFAULT ?
ceil(2 * param
[0]) : 6;
305 else if (flags
& SWS_SINC
)
306 sizeFactor
= 20; // infinite ;)
307 else if (flags
& SWS_SPLINE
)
308 sizeFactor
= 20; // infinite ;)
309 else if (flags
& SWS_BILINEAR
)
312 sizeFactor
= 0; // GCC warning killer
317 filterSize
= 1 + sizeFactor
; // upscale
319 filterSize
= 1 + (sizeFactor
* srcW
+ dstW
- 1) / dstW
;
321 filterSize
= FFMIN(filterSize
, srcW
- 2);
322 filterSize
= FFMAX(filterSize
, 1);
324 FF_ALLOC_OR_GOTO(NULL
, filter
,
325 dstW
* sizeof(*filter
) * filterSize
, fail
);
327 xDstInSrc
= xInc
- 0x10000;
328 for (i
= 0; i
< dstW
; i
++) {
329 int xx
= (xDstInSrc
- ((filterSize
- 2) << 16)) / (1 << 17);
331 (*filterPos
)[i
] = xx
;
332 for (j
= 0; j
< filterSize
; j
++) {
333 int64_t d
= (FFABS(((int64_t)xx
<< 17) - xDstInSrc
)) << 13;
339 floatd
= d
* (1.0 / (1 << 30));
341 if (flags
& SWS_BICUBIC
) {
342 int64_t B
= (param
[0] != SWS_PARAM_DEFAULT ? param
[0] : 0) * (1 << 24);
343 int64_t C
= (param
[1] != SWS_PARAM_DEFAULT ? param
[1] : 0.6) * (1 << 24);
345 if (d
>= 1LL << 31) {
348 int64_t dd
= (d
* d
) >> 30;
349 int64_t ddd
= (dd
* d
) >> 30;
352 coeff
= (12 * (1 << 24) - 9 * B
- 6 * C
) * ddd
+
353 (-18 * (1 << 24) + 12 * B
+ 6 * C
) * dd
+
354 (6 * (1 << 24) - 2 * B
) * (1 << 30);
356 coeff
= (-B
- 6 * C
) * ddd
+
357 (6 * B
+ 30 * C
) * dd
+
358 (-12 * B
- 48 * C
) * d
+
359 (8 * B
+ 24 * C
) * (1 << 30);
361 coeff
*= fone
>> (30 + 24);
364 else if (flags
& SWS_X
) {
365 double p
= param ? param
* 0.01 : 0.3;
366 coeff
= d ?
sin(d
* M_PI
) / (d
* M_PI
) : 1.0;
367 coeff
*= pow(2.0, -p
* d
* d
);
370 else if (flags
& SWS_X
) {
371 double A
= param
[0] != SWS_PARAM_DEFAULT ? param
[0] : 1.0;
375 c
= cos(floatd
* M_PI
);
382 coeff
= (c
* 0.5 + 0.5) * fone
;
383 } else if (flags
& SWS_AREA
) {
384 int64_t d2
= d
- (1 << 29);
385 if (d2
* xInc
< -(1LL << (29 + 16)))
386 coeff
= 1.0 * (1LL << (30 + 16));
387 else if (d2
* xInc
< (1LL << (29 + 16)))
388 coeff
= -d2
* xInc
+ (1LL << (29 + 16));
391 coeff
*= fone
>> (30 + 16);
392 } else if (flags
& SWS_GAUSS
) {
393 double p
= param
[0] != SWS_PARAM_DEFAULT ? param
[0] : 3.0;
394 coeff
= (pow(2.0, -p
* floatd
* floatd
)) * fone
;
395 } else if (flags
& SWS_SINC
) {
396 coeff
= (d ?
sin(floatd
* M_PI
) / (floatd
* M_PI
) : 1.0) * fone
;
397 } else if (flags
& SWS_LANCZOS
) {
398 double p
= param
[0] != SWS_PARAM_DEFAULT ? param
[0] : 3.0;
399 coeff
= (d ?
sin(floatd
* M_PI
) * sin(floatd
* M_PI
/ p
) /
400 (floatd
* floatd
* M_PI
* M_PI
/ p
) : 1.0) * fone
;
403 } else if (flags
& SWS_BILINEAR
) {
404 coeff
= (1 << 30) - d
;
408 } else if (flags
& SWS_SPLINE
) {
409 double p
= -2.196152422706632;
410 coeff
= getSplineCoeff(1.0, 0.0, p
, -p
- 1.0, floatd
) * fone
;
412 coeff
= 0.0; // GCC warning killer
416 filter
[i
* filterSize
+ j
] = coeff
;
419 xDstInSrc
+= 2 * xInc
;
423 /* apply src & dst Filter to filter -> filter2
426 assert(filterSize
> 0);
427 filter2Size
= filterSize
;
429 filter2Size
+= srcFilter
->length
- 1;
431 filter2Size
+= dstFilter
->length
- 1;
432 assert(filter2Size
> 0);
433 FF_ALLOCZ_OR_GOTO(NULL
, filter2
, filter2Size
* dstW
* sizeof(*filter2
), fail
);
435 for (i
= 0; i
< dstW
; i
++) {
439 for (k
= 0; k
< srcFilter
->length
; k
++) {
440 for (j
= 0; j
< filterSize
; j
++)
441 filter2
[i
* filter2Size
+ k
+ j
] +=
442 srcFilter
->coeff
[k
] * filter
[i
* filterSize
+ j
];
445 for (j
= 0; j
< filterSize
; j
++)
446 filter2
[i
* filter2Size
+ j
] = filter
[i
* filterSize
+ j
];
450 (*filterPos
)[i
] += (filterSize
- 1) / 2 - (filter2Size
- 1) / 2;
454 /* try to reduce the filter-size (step1 find size and shift left) */
455 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
457 for (i
= dstW
- 1; i
>= 0; i
--) {
458 int min
= filter2Size
;
460 int64_t cutOff
= 0.0;
462 /* get rid of near zero elements on the left by shifting left */
463 for (j
= 0; j
< filter2Size
; j
++) {
465 cutOff
+= FFABS(filter2
[i
* filter2Size
]);
467 if (cutOff
> SWS_MAX_REDUCE_CUTOFF
* fone
)
470 /* preserve monotonicity because the core can't handle the
471 * filter otherwise */
472 if (i
< dstW
- 1 && (*filterPos
)[i
] >= (*filterPos
)[i
+ 1])
475 // move filter coefficients left
476 for (k
= 1; k
< filter2Size
; k
++)
477 filter2
[i
* filter2Size
+ k
- 1] = filter2
[i
* filter2Size
+ k
];
478 filter2
[i
* filter2Size
+ k
- 1] = 0;
483 /* count near zeros on the right */
484 for (j
= filter2Size
- 1; j
> 0; j
--) {
485 cutOff
+= FFABS(filter2
[i
* filter2Size
+ j
]);
487 if (cutOff
> SWS_MAX_REDUCE_CUTOFF
* fone
)
492 if (min
> minFilterSize
)
496 if (PPC_ALTIVEC(cpu_flags
)) {
497 // we can handle the special case 4, so we don't want to go the full 8
498 if (minFilterSize
< 5)
501 /* We really don't want to waste our time doing useless computation, so
502 * fall back on the scalar C code for very small filters.
503 * Vectorizing is worth it only if you have a decent-sized vector. */
504 if (minFilterSize
< 3)
508 if (INLINE_MMX(cpu_flags
)) {
509 // special case for unscaled vertical filtering
510 if (minFilterSize
== 1 && filterAlign
== 2)
514 assert(minFilterSize
> 0);
515 filterSize
= (minFilterSize
+ (filterAlign
- 1)) & (~(filterAlign
- 1));
516 assert(filterSize
> 0);
517 filter
= av_malloc(filterSize
* dstW
* sizeof(*filter
));
518 if (filterSize
>= MAX_FILTER_SIZE
* 16 /
519 ((flags
& SWS_ACCURATE_RND
) ? APCK_SIZE
: 16) || !filter
)
521 *outFilterSize
= filterSize
;
523 if (flags
& SWS_PRINT_INFO
)
524 av_log(NULL
, AV_LOG_VERBOSE
,
525 "SwScaler: reducing / aligning filtersize %d -> %d\n",
526 filter2Size
, filterSize
);
527 /* try to reduce the filter-size (step2 reduce it) */
528 for (i
= 0; i
< dstW
; i
++) {
531 for (j
= 0; j
< filterSize
; j
++) {
532 if (j
>= filter2Size
)
533 filter
[i
* filterSize
+ j
] = 0;
535 filter
[i
* filterSize
+ j
] = filter2
[i
* filter2Size
+ j
];
536 if ((flags
& SWS_BITEXACT
) && j
>= minFilterSize
)
537 filter
[i
* filterSize
+ j
] = 0;
541 // FIXME try to align filterPos if possible
545 for (i
= 0; i
< dstW
; i
++) {
547 if ((*filterPos
)[i
] < 0) {
548 // move filter coefficients left to compensate for filterPos
549 for (j
= 1; j
< filterSize
; j
++) {
550 int left
= FFMAX(j
+ (*filterPos
)[i
], 0);
551 filter
[i
* filterSize
+ left
] += filter
[i
* filterSize
+ j
];
552 filter
[i
* filterSize
+ j
] = 0;
557 if ((*filterPos
)[i
] + filterSize
> srcW
) {
558 int shift
= (*filterPos
)[i
] + filterSize
- srcW
;
559 // move filter coefficients right to compensate for filterPos
560 for (j
= filterSize
- 2; j
>= 0; j
--) {
561 int right
= FFMIN(j
+ shift
, filterSize
- 1);
562 filter
[i
* filterSize
+ right
] += filter
[i
* filterSize
+ j
];
563 filter
[i
* filterSize
+ j
] = 0;
565 (*filterPos
)[i
] = srcW
- filterSize
;
570 // Note the +1 is for the MMX scaler which reads over the end
571 /* align at 16 for AltiVec (needed by hScale_altivec_real) */
572 FF_ALLOCZ_OR_GOTO(NULL
, *outFilter
,
573 *outFilterSize
* (dstW
+ 3) * sizeof(int16_t), fail
);
575 /* normalize & store in outFilter */
576 for (i
= 0; i
< dstW
; i
++) {
581 for (j
= 0; j
< filterSize
; j
++) {
582 sum
+= filter
[i
* filterSize
+ j
];
584 sum
= (sum
+ one
/ 2) / one
;
585 for (j
= 0; j
< *outFilterSize
; j
++) {
586 int64_t v
= filter
[i
* filterSize
+ j
] + error
;
587 int intV
= ROUNDED_DIV(v
, sum
);
588 (*outFilter
)[i
* (*outFilterSize
) + j
] = intV
;
589 error
= v
- intV
* sum
;
593 (*filterPos
)[dstW
+ 0] =
594 (*filterPos
)[dstW
+ 1] =
595 (*filterPos
)[dstW
+ 2] = (*filterPos
)[dstW
- 1]; /* the MMX/SSE scaler will
596 * read over the end */
597 for (i
= 0; i
< *outFilterSize
; i
++) {
598 int k
= (dstW
- 1) * (*outFilterSize
) + i
;
599 (*outFilter
)[k
+ 1 * (*outFilterSize
)] =
600 (*outFilter
)[k
+ 2 * (*outFilterSize
)] =
601 (*outFilter
)[k
+ 3 * (*outFilterSize
)] = (*outFilter
)[k
];
612 #if HAVE_MMXEXT_INLINE
613 static av_cold
int init_hscaler_mmxext(int dstW
, int xInc
, uint8_t *filterCode
,
614 int16_t *filter
, int32_t *filterPos
,
618 x86_reg imm8OfPShufW1A
;
619 x86_reg imm8OfPShufW2A
;
620 x86_reg fragmentLengthA
;
622 x86_reg imm8OfPShufW1B
;
623 x86_reg imm8OfPShufW2B
;
624 x86_reg fragmentLengthB
;
629 // create an optimized horizontal scaling routine
630 /* This scaler is made of runtime-generated MMXEXT code using specially tuned
631 * pshufw instructions. For every four output pixels, if four input pixels
632 * are enough for the fast bilinear scaling, then a chunk of fragmentB is
633 * used. If five input pixels are needed, then a chunk of fragmentA is used.
642 "movq (%%"REG_d
", %%"REG_a
"), %%mm3 \n\t"
643 "movd (%%"REG_c
", %%"REG_S
"), %%mm0 \n\t"
644 "movd 1(%%"REG_c
", %%"REG_S
"), %%mm1 \n\t"
645 "punpcklbw %%mm7, %%mm1 \n\t"
646 "punpcklbw %%mm7, %%mm0 \n\t"
647 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
649 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
651 "psubw %%mm1, %%mm0 \n\t"
652 "movl 8(%%"REG_b
", %%"REG_a
"), %%esi \n\t"
653 "pmullw %%mm3, %%mm0 \n\t"
654 "psllw $7, %%mm1 \n\t"
655 "paddw %%mm1, %%mm0 \n\t"
657 "movq %%mm0, (%%"REG_D
", %%"REG_a
") \n\t"
659 "add $8, %%"REG_a
" \n\t"
663 "lea " LOCAL_MANGLE(0b
) ", %0 \n\t"
664 "lea " LOCAL_MANGLE(1b
) ", %1 \n\t"
665 "lea " LOCAL_MANGLE(2b
) ", %2 \n\t"
670 "lea " LOCAL_MANGLE(9b
) ", %3 \n\t"
674 : "=r" (fragmentA
), "=r" (imm8OfPShufW1A
), "=r" (imm8OfPShufW2A
),
675 "=r" (fragmentLengthA
)
682 "movq (%%"REG_d
", %%"REG_a
"), %%mm3 \n\t"
683 "movd (%%"REG_c
", %%"REG_S
"), %%mm0 \n\t"
684 "punpcklbw %%mm7, %%mm0 \n\t"
685 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
687 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
689 "psubw %%mm1, %%mm0 \n\t"
690 "movl 8(%%"REG_b
", %%"REG_a
"), %%esi \n\t"
691 "pmullw %%mm3, %%mm0 \n\t"
692 "psllw $7, %%mm1 \n\t"
693 "paddw %%mm1, %%mm0 \n\t"
695 "movq %%mm0, (%%"REG_D
", %%"REG_a
") \n\t"
697 "add $8, %%"REG_a
" \n\t"
701 "lea " LOCAL_MANGLE(0b
) ", %0 \n\t"
702 "lea " LOCAL_MANGLE(1b
) ", %1 \n\t"
703 "lea " LOCAL_MANGLE(2b
) ", %2 \n\t"
708 "lea " LOCAL_MANGLE(9b
) ", %3 \n\t"
712 : "=r" (fragmentB
), "=r" (imm8OfPShufW1B
), "=r" (imm8OfPShufW2B
),
713 "=r" (fragmentLengthB
)
716 xpos
= 0; // lumXInc/2 - 0x8000; // difference between pixel centers
719 for (i
= 0; i
< dstW
/ numSplits
; i
++) {
724 int b
= ((xpos
+ xInc
) >> 16) - xx
;
725 int c
= ((xpos
+ xInc
* 2) >> 16) - xx
;
726 int d
= ((xpos
+ xInc
* 3) >> 16) - xx
;
727 int inc
= (d
+ 1 < 4);
728 uint8_t *fragment
= (d
+ 1 < 4) ? fragmentB
: fragmentA
;
729 x86_reg imm8OfPShufW1
= (d
+ 1 < 4) ? imm8OfPShufW1B
: imm8OfPShufW1A
;
730 x86_reg imm8OfPShufW2
= (d
+ 1 < 4) ? imm8OfPShufW2B
: imm8OfPShufW2A
;
731 x86_reg fragmentLength
= (d
+ 1 < 4) ? fragmentLengthB
: fragmentLengthA
;
732 int maxShift
= 3 - (d
+ inc
);
736 filter
[i
] = ((xpos
& 0xFFFF) ^ 0xFFFF) >> 9;
737 filter
[i
+ 1] = (((xpos
+ xInc
) & 0xFFFF) ^ 0xFFFF) >> 9;
738 filter
[i
+ 2] = (((xpos
+ xInc
* 2) & 0xFFFF) ^ 0xFFFF) >> 9;
739 filter
[i
+ 3] = (((xpos
+ xInc
* 3) & 0xFFFF) ^ 0xFFFF) >> 9;
740 filterPos
[i
/ 2] = xx
;
742 memcpy(filterCode
+ fragmentPos
, fragment
, fragmentLength
);
744 filterCode
[fragmentPos
+ imm8OfPShufW1
] = (a
+ inc
) |
748 filterCode
[fragmentPos
+ imm8OfPShufW2
] = a
| (b
<< 2) |
752 if (i
+ 4 - inc
>= dstW
)
753 shift
= maxShift
; // avoid overread
754 else if ((filterPos
[i
/ 2] & 3) <= maxShift
)
755 shift
= filterPos
[i
/ 2] & 3; // align
757 if (shift
&& i
>= shift
) {
758 filterCode
[fragmentPos
+ imm8OfPShufW1
] += 0x55 * shift
;
759 filterCode
[fragmentPos
+ imm8OfPShufW2
] += 0x55 * shift
;
760 filterPos
[i
/ 2] -= shift
;
764 fragmentPos
+= fragmentLength
;
767 filterCode
[fragmentPos
] = RET
;
772 filterPos
[((i
/ 2) + 1) & (~1)] = xpos
>> 16; // needed to jump to the next part
774 return fragmentPos
+ 1;
776 #endif /* HAVE_MMXEXT_INLINE */
778 static void getSubSampleFactors(int *h
, int *v
, enum AVPixelFormat format
)
780 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(format
);
781 *h
= desc
->log2_chroma_w
;
782 *v
= desc
->log2_chroma_h
;
785 int sws_setColorspaceDetails(struct SwsContext
*c
, const int inv_table
[4],
786 int srcRange
, const int table
[4], int dstRange
,
787 int brightness
, int contrast
, int saturation
)
789 const AVPixFmtDescriptor
*desc_dst
= av_pix_fmt_desc_get(c
->dstFormat
);
790 const AVPixFmtDescriptor
*desc_src
= av_pix_fmt_desc_get(c
->srcFormat
);
791 memcpy(c
->srcColorspaceTable
, inv_table
, sizeof(int) * 4);
792 memcpy(c
->dstColorspaceTable
, table
, sizeof(int) * 4);
794 c
->brightness
= brightness
;
795 c
->contrast
= contrast
;
796 c
->saturation
= saturation
;
797 c
->srcRange
= srcRange
;
798 c
->dstRange
= dstRange
;
799 if (isYUV(c
->dstFormat
) || isGray(c
->dstFormat
))
802 c
->dstFormatBpp
= av_get_bits_per_pixel(desc_dst
);
803 c
->srcFormatBpp
= av_get_bits_per_pixel(desc_src
);
805 ff_yuv2rgb_c_init_tables(c
, inv_table
, srcRange
, brightness
,
806 contrast
, saturation
);
810 ff_yuv2rgb_init_tables_ppc(c
, inv_table
, brightness
,
811 contrast
, saturation
);
815 int sws_getColorspaceDetails(struct SwsContext
*c
, int **inv_table
,
816 int *srcRange
, int **table
, int *dstRange
,
817 int *brightness
, int *contrast
, int *saturation
)
819 if (isYUV(c
->dstFormat
) || isGray(c
->dstFormat
))
822 *inv_table
= c
->srcColorspaceTable
;
823 *table
= c
->dstColorspaceTable
;
824 *srcRange
= c
->srcRange
;
825 *dstRange
= c
->dstRange
;
826 *brightness
= c
->brightness
;
827 *contrast
= c
->contrast
;
828 *saturation
= c
->saturation
;
833 static int handle_jpeg(enum AVPixelFormat
*format
)
836 case AV_PIX_FMT_YUVJ420P
:
837 *format
= AV_PIX_FMT_YUV420P
;
839 case AV_PIX_FMT_YUVJ422P
:
840 *format
= AV_PIX_FMT_YUV422P
;
842 case AV_PIX_FMT_YUVJ444P
:
843 *format
= AV_PIX_FMT_YUV444P
;
845 case AV_PIX_FMT_YUVJ440P
:
846 *format
= AV_PIX_FMT_YUV440P
;
853 SwsContext
*sws_alloc_context(void)
855 SwsContext
*c
= av_mallocz(sizeof(SwsContext
));
858 c
->av_class
= &sws_context_class
;
859 av_opt_set_defaults(c
);
865 av_cold
int sws_init_context(SwsContext
*c
, SwsFilter
*srcFilter
,
866 SwsFilter
*dstFilter
)
869 int usesVFilter
, usesHFilter
;
871 SwsFilter dummyFilter
= { NULL
, NULL
, NULL
, NULL
};
876 int dst_stride
= FFALIGN(dstW
* sizeof(int16_t) + 16, 16);
877 int dst_stride_px
= dst_stride
>> 1;
878 int flags
, cpu_flags
;
879 enum AVPixelFormat srcFormat
= c
->srcFormat
;
880 enum AVPixelFormat dstFormat
= c
->dstFormat
;
881 const AVPixFmtDescriptor
*desc_src
= av_pix_fmt_desc_get(srcFormat
);
882 const AVPixFmtDescriptor
*desc_dst
= av_pix_fmt_desc_get(dstFormat
);
884 cpu_flags
= av_get_cpu_flags();
890 unscaled
= (srcW
== dstW
&& srcH
== dstH
);
892 if (!(unscaled
&& sws_isSupportedEndiannessConversion(srcFormat
) &&
893 av_pix_fmt_swap_endianness(srcFormat
) == dstFormat
)) {
894 if (!sws_isSupportedInput(srcFormat
)) {
895 av_log(c
, AV_LOG_ERROR
, "%s is not supported as input pixel format\n",
896 sws_format_name(srcFormat
));
897 return AVERROR(EINVAL
);
899 if (!sws_isSupportedOutput(dstFormat
)) {
900 av_log(c
, AV_LOG_ERROR
, "%s is not supported as output pixel format\n",
901 sws_format_name(dstFormat
));
902 return AVERROR(EINVAL
);
906 i
= flags
& (SWS_POINT
|
918 /* provide a default scaler if not set by caller */
920 if (dstW
< srcW
&& dstH
< srcH
)
922 else if (dstW
> srcW
&& dstH
> srcH
)
925 flags
|= SWS_LANCZOS
;
927 } else if (i
& (i
- 1)) {
928 av_log(c
, AV_LOG_ERROR
,
929 "Exactly one scaler algorithm must be chosen\n");
930 return AVERROR(EINVAL
);
933 if (srcW
< 4 || srcH
< 1 || dstW
< 8 || dstH
< 1) {
934 /* FIXME check if these are enough and try to lower them after
935 * fixing the relevant parts of the code */
936 av_log(c
, AV_LOG_ERROR
, "%dx%d -> %dx%d is invalid scaling dimension\n",
937 srcW
, srcH
, dstW
, dstH
);
938 return AVERROR(EINVAL
);
942 dstFilter
= &dummyFilter
;
944 srcFilter
= &dummyFilter
;
946 c
->lumXInc
= (((int64_t)srcW
<< 16) + (dstW
>> 1)) / dstW
;
947 c
->lumYInc
= (((int64_t)srcH
<< 16) + (dstH
>> 1)) / dstH
;
948 c
->dstFormatBpp
= av_get_bits_per_pixel(desc_dst
);
949 c
->srcFormatBpp
= av_get_bits_per_pixel(desc_src
);
950 c
->vRounder
= 4 * 0x0001000100010001ULL
;
952 usesVFilter
= (srcFilter
->lumV
&& srcFilter
->lumV
->length
> 1) ||
953 (srcFilter
->chrV
&& srcFilter
->chrV
->length
> 1) ||
954 (dstFilter
->lumV
&& dstFilter
->lumV
->length
> 1) ||
955 (dstFilter
->chrV
&& dstFilter
->chrV
->length
> 1);
956 usesHFilter
= (srcFilter
->lumH
&& srcFilter
->lumH
->length
> 1) ||
957 (srcFilter
->chrH
&& srcFilter
->chrH
->length
> 1) ||
958 (dstFilter
->lumH
&& dstFilter
->lumH
->length
> 1) ||
959 (dstFilter
->chrH
&& dstFilter
->chrH
->length
> 1);
961 getSubSampleFactors(&c
->chrSrcHSubSample
, &c
->chrSrcVSubSample
, srcFormat
);
962 getSubSampleFactors(&c
->chrDstHSubSample
, &c
->chrDstVSubSample
, dstFormat
);
964 if (isPlanarRGB(dstFormat
)) {
965 if (!(flags
& SWS_FULL_CHR_H_INT
)) {
966 av_log(c
, AV_LOG_DEBUG
,
967 "%s output is not supported with half chroma resolution, switching to full\n",
968 av_get_pix_fmt_name(dstFormat
));
969 flags
|= SWS_FULL_CHR_H_INT
;
974 /* reuse chroma for 2 pixels RGB/BGR unless user wants full
975 * chroma interpolation */
976 if (flags
& SWS_FULL_CHR_H_INT
&&
977 isAnyRGB(dstFormat
) &&
978 !isPlanarRGB(dstFormat
) &&
979 dstFormat
!= AV_PIX_FMT_RGBA
&&
980 dstFormat
!= AV_PIX_FMT_ARGB
&&
981 dstFormat
!= AV_PIX_FMT_BGRA
&&
982 dstFormat
!= AV_PIX_FMT_ABGR
&&
983 dstFormat
!= AV_PIX_FMT_RGB24
&&
984 dstFormat
!= AV_PIX_FMT_BGR24
) {
985 av_log(c
, AV_LOG_ERROR
,
986 "full chroma interpolation for destination format '%s' not yet implemented\n",
987 sws_format_name(dstFormat
));
988 flags
&= ~SWS_FULL_CHR_H_INT
;
991 if (isAnyRGB(dstFormat
) && !(flags
& SWS_FULL_CHR_H_INT
))
992 c
->chrDstHSubSample
= 1;
994 // drop some chroma lines if the user wants it
995 c
->vChrDrop
= (flags
& SWS_SRC_V_CHR_DROP_MASK
) >>
996 SWS_SRC_V_CHR_DROP_SHIFT
;
997 c
->chrSrcVSubSample
+= c
->vChrDrop
;
999 /* drop every other pixel for chroma calculation unless user
1000 * wants full chroma */
1001 if (isAnyRGB(srcFormat
) && !(flags
& SWS_FULL_CHR_H_INP
) &&
1002 srcFormat
!= AV_PIX_FMT_RGB8
&& srcFormat
!= AV_PIX_FMT_BGR8
&&
1003 srcFormat
!= AV_PIX_FMT_RGB4
&& srcFormat
!= AV_PIX_FMT_BGR4
&&
1004 srcFormat
!= AV_PIX_FMT_RGB4_BYTE
&& srcFormat
!= AV_PIX_FMT_BGR4_BYTE
&&
1005 srcFormat
!= AV_PIX_FMT_GBRP9BE
&& srcFormat
!= AV_PIX_FMT_GBRP9LE
&&
1006 srcFormat
!= AV_PIX_FMT_GBRP10BE
&& srcFormat
!= AV_PIX_FMT_GBRP10LE
&&
1007 srcFormat
!= AV_PIX_FMT_GBRP16BE
&& srcFormat
!= AV_PIX_FMT_GBRP16LE
&&
1008 ((dstW
>> c
->chrDstHSubSample
) <= (srcW
>> 1) ||
1009 (flags
& SWS_FAST_BILINEAR
)))
1010 c
->chrSrcHSubSample
= 1;
1012 // Note the -((-x)>>y) is so that we always round toward +inf.
1013 c
->chrSrcW
= -((-srcW
) >> c
->chrSrcHSubSample
);
1014 c
->chrSrcH
= -((-srcH
) >> c
->chrSrcVSubSample
);
1015 c
->chrDstW
= -((-dstW
) >> c
->chrDstHSubSample
);
1016 c
->chrDstH
= -((-dstH
) >> c
->chrDstVSubSample
);
1018 /* unscaled special cases */
1019 if (unscaled
&& !usesHFilter
&& !usesVFilter
&&
1020 (c
->srcRange
== c
->dstRange
|| isAnyRGB(dstFormat
))) {
1021 ff_get_unscaled_swscale(c
);
1024 if (flags
& SWS_PRINT_INFO
)
1025 av_log(c
, AV_LOG_INFO
,
1026 "using unscaled %s -> %s special converter\n",
1027 sws_format_name(srcFormat
), sws_format_name(dstFormat
));
1032 c
->srcBpc
= 1 + desc_src
->comp
[0].depth_minus1
;
1035 c
->dstBpc
= 1 + desc_dst
->comp
[0].depth_minus1
;
1038 if (c
->dstBpc
== 16)
1040 FF_ALLOC_OR_GOTO(c
, c
->formatConvBuffer
,
1041 (FFALIGN(srcW
, 16) * 2 * FFALIGN(c
->srcBpc
, 8) >> 3) + 16,
1043 if (INLINE_MMXEXT(cpu_flags
) && c
->srcBpc
== 8 && c
->dstBpc
<= 10) {
1044 c
->canMMXEXTBeUsed
= (dstW
>= srcW
&& (dstW
& 31) == 0 &&
1045 (srcW
& 15) == 0) ?
1 : 0;
1046 if (!c
->canMMXEXTBeUsed
&& dstW
>= srcW
&& (srcW
& 15) == 0
1047 && (flags
& SWS_FAST_BILINEAR
)) {
1048 if (flags
& SWS_PRINT_INFO
)
1049 av_log(c
, AV_LOG_INFO
,
1050 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
1053 c
->canMMXEXTBeUsed
= 0;
1055 c
->canMMXEXTBeUsed
= 0;
1057 c
->chrXInc
= (((int64_t)c
->chrSrcW
<< 16) + (c
->chrDstW
>> 1)) / c
->chrDstW
;
1058 c
->chrYInc
= (((int64_t)c
->chrSrcH
<< 16) + (c
->chrDstH
>> 1)) / c
->chrDstH
;
1060 /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
1061 * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
1063 * n-2 is the last chrominance sample available.
1064 * This is not perfect, but no one should notice the difference, the more
1065 * correct variant would be like the vertical one, but that would require
1066 * some special code for the first and last pixel */
1067 if (flags
& SWS_FAST_BILINEAR
) {
1068 if (c
->canMMXEXTBeUsed
) {
1072 // we don't use the x86 asm scaler if MMX is available
1073 else if (INLINE_MMX(cpu_flags
)) {
1074 c
->lumXInc
= ((int64_t)(srcW
- 2) << 16) / (dstW
- 2) - 20;
1075 c
->chrXInc
= ((int64_t)(c
->chrSrcW
- 2) << 16) / (c
->chrDstW
- 2) - 20;
1079 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
1081 /* precalculate horizontal scaler filter coefficients */
1083 #if HAVE_MMXEXT_INLINE
1084 // can't downscale !!!
1085 if (c
->canMMXEXTBeUsed
&& (flags
& SWS_FAST_BILINEAR
)) {
1086 c
->lumMmxextFilterCodeSize
= init_hscaler_mmxext(dstW
, c
->lumXInc
, NULL
,
1088 c
->chrMmxextFilterCodeSize
= init_hscaler_mmxext(c
->chrDstW
, c
->chrXInc
,
1089 NULL
, NULL
, NULL
, 4);
1092 c
->lumMmxextFilterCode
= mmap(NULL
, c
->lumMmxextFilterCodeSize
,
1093 PROT_READ
| PROT_WRITE
,
1094 MAP_PRIVATE
| MAP_ANONYMOUS
,
1096 c
->chrMmxextFilterCode
= mmap(NULL
, c
->chrMmxextFilterCodeSize
,
1097 PROT_READ
| PROT_WRITE
,
1098 MAP_PRIVATE
| MAP_ANONYMOUS
,
1100 #elif HAVE_VIRTUALALLOC
1101 c
->lumMmxextFilterCode
= VirtualAlloc(NULL
,
1102 c
->lumMmxextFilterCodeSize
,
1104 PAGE_EXECUTE_READWRITE
);
1105 c
->chrMmxextFilterCode
= VirtualAlloc(NULL
,
1106 c
->chrMmxextFilterCodeSize
,
1108 PAGE_EXECUTE_READWRITE
);
1110 c
->lumMmxextFilterCode
= av_malloc(c
->lumMmxextFilterCodeSize
);
1111 c
->chrMmxextFilterCode
= av_malloc(c
->chrMmxextFilterCodeSize
);
1114 if (!c
->lumMmxextFilterCode
|| !c
->chrMmxextFilterCode
)
1115 return AVERROR(ENOMEM
);
1116 FF_ALLOCZ_OR_GOTO(c
, c
->hLumFilter
, (dstW
/ 8 + 8) * sizeof(int16_t), fail
);
1117 FF_ALLOCZ_OR_GOTO(c
, c
->hChrFilter
, (c
->chrDstW
/ 4 + 8) * sizeof(int16_t), fail
);
1118 FF_ALLOCZ_OR_GOTO(c
, c
->hLumFilterPos
, (dstW
/ 2 / 8 + 8) * sizeof(int32_t), fail
);
1119 FF_ALLOCZ_OR_GOTO(c
, c
->hChrFilterPos
, (c
->chrDstW
/ 2 / 4 + 8) * sizeof(int32_t), fail
);
1121 init_hscaler_mmxext(dstW
, c
->lumXInc
, c
->lumMmxextFilterCode
,
1122 c
->hLumFilter
, c
->hLumFilterPos
, 8);
1123 init_hscaler_mmxext(c
->chrDstW
, c
->chrXInc
, c
->chrMmxextFilterCode
,
1124 c
->hChrFilter
, c
->hChrFilterPos
, 4);
1127 mprotect(c
->lumMmxextFilterCode
, c
->lumMmxextFilterCodeSize
, PROT_EXEC
| PROT_READ
);
1128 mprotect(c
->chrMmxextFilterCode
, c
->chrMmxextFilterCodeSize
, PROT_EXEC
| PROT_READ
);
1131 #endif /* HAVE_MMXEXT_INLINE */
1133 const int filterAlign
= X86_MMX(cpu_flags
) ?
4 :
1134 PPC_ALTIVEC(cpu_flags
) ?
8 : 1;
1136 if (initFilter(&c
->hLumFilter
, &c
->hLumFilterPos
,
1137 &c
->hLumFilterSize
, c
->lumXInc
,
1138 srcW
, dstW
, filterAlign
, 1 << 14,
1139 (flags
& SWS_BICUBLIN
) ?
(flags
| SWS_BICUBIC
) : flags
,
1140 cpu_flags
, srcFilter
->lumH
, dstFilter
->lumH
,
1143 if (initFilter(&c
->hChrFilter
, &c
->hChrFilterPos
,
1144 &c
->hChrFilterSize
, c
->chrXInc
,
1145 c
->chrSrcW
, c
->chrDstW
, filterAlign
, 1 << 14,
1146 (flags
& SWS_BICUBLIN
) ?
(flags
| SWS_BILINEAR
) : flags
,
1147 cpu_flags
, srcFilter
->chrH
, dstFilter
->chrH
,
1151 } // initialize horizontal stuff
1153 /* precalculate vertical scaler filter coefficients */
1155 const int filterAlign
= X86_MMX(cpu_flags
) ?
2 :
1156 PPC_ALTIVEC(cpu_flags
) ?
8 : 1;
1158 if (initFilter(&c
->vLumFilter
, &c
->vLumFilterPos
, &c
->vLumFilterSize
,
1159 c
->lumYInc
, srcH
, dstH
, filterAlign
, (1 << 12),
1160 (flags
& SWS_BICUBLIN
) ?
(flags
| SWS_BICUBIC
) : flags
,
1161 cpu_flags
, srcFilter
->lumV
, dstFilter
->lumV
,
1164 if (initFilter(&c
->vChrFilter
, &c
->vChrFilterPos
, &c
->vChrFilterSize
,
1165 c
->chrYInc
, c
->chrSrcH
, c
->chrDstH
,
1166 filterAlign
, (1 << 12),
1167 (flags
& SWS_BICUBLIN
) ?
(flags
| SWS_BILINEAR
) : flags
,
1168 cpu_flags
, srcFilter
->chrV
, dstFilter
->chrV
,
1173 FF_ALLOC_OR_GOTO(c
, c
->vYCoeffsBank
, sizeof(vector
signed short) * c
->vLumFilterSize
* c
->dstH
, fail
);
1174 FF_ALLOC_OR_GOTO(c
, c
->vCCoeffsBank
, sizeof(vector
signed short) * c
->vChrFilterSize
* c
->chrDstH
, fail
);
1176 for (i
= 0; i
< c
->vLumFilterSize
* c
->dstH
; i
++) {
1178 short *p
= (short *)&c
->vYCoeffsBank
[i
];
1179 for (j
= 0; j
< 8; j
++)
1180 p
[j
] = c
->vLumFilter
[i
];
1183 for (i
= 0; i
< c
->vChrFilterSize
* c
->chrDstH
; i
++) {
1185 short *p
= (short *)&c
->vCCoeffsBank
[i
];
1186 for (j
= 0; j
< 8; j
++)
1187 p
[j
] = c
->vChrFilter
[i
];
1192 // calculate buffer sizes so that they won't run out while handling these damn slices
1193 c
->vLumBufSize
= c
->vLumFilterSize
;
1194 c
->vChrBufSize
= c
->vChrFilterSize
;
1195 for (i
= 0; i
< dstH
; i
++) {
1196 int chrI
= (int64_t)i
* c
->chrDstH
/ dstH
;
1197 int nextSlice
= FFMAX(c
->vLumFilterPos
[i
] + c
->vLumFilterSize
- 1,
1198 ((c
->vChrFilterPos
[chrI
] + c
->vChrFilterSize
- 1)
1199 << c
->chrSrcVSubSample
));
1201 nextSlice
>>= c
->chrSrcVSubSample
;
1202 nextSlice
<<= c
->chrSrcVSubSample
;
1203 if (c
->vLumFilterPos
[i
] + c
->vLumBufSize
< nextSlice
)
1204 c
->vLumBufSize
= nextSlice
- c
->vLumFilterPos
[i
];
1205 if (c
->vChrFilterPos
[chrI
] + c
->vChrBufSize
<
1206 (nextSlice
>> c
->chrSrcVSubSample
))
1207 c
->vChrBufSize
= (nextSlice
>> c
->chrSrcVSubSample
) -
1208 c
->vChrFilterPos
[chrI
];
1211 /* Allocate pixbufs (we use dynamic allocation because otherwise we would
1212 * need to allocate several megabytes to handle all possible cases) */
1213 FF_ALLOC_OR_GOTO(c
, c
->lumPixBuf
, c
->vLumBufSize
* 3 * sizeof(int16_t *), fail
);
1214 FF_ALLOC_OR_GOTO(c
, c
->chrUPixBuf
, c
->vChrBufSize
* 3 * sizeof(int16_t *), fail
);
1215 FF_ALLOC_OR_GOTO(c
, c
->chrVPixBuf
, c
->vChrBufSize
* 3 * sizeof(int16_t *), fail
);
1216 if (CONFIG_SWSCALE_ALPHA
&& isALPHA(c
->srcFormat
) && isALPHA(c
->dstFormat
))
1217 FF_ALLOCZ_OR_GOTO(c
, c
->alpPixBuf
, c
->vLumBufSize
* 3 * sizeof(int16_t *), fail
);
1218 /* Note we need at least one pixel more at the end because of the MMX code
1219 * (just in case someone wants to replace the 4000/8000). */
1220 /* align at 16 bytes for AltiVec */
1221 for (i
= 0; i
< c
->vLumBufSize
; i
++) {
1222 FF_ALLOCZ_OR_GOTO(c
, c
->lumPixBuf
[i
+ c
->vLumBufSize
],
1223 dst_stride
+ 16, fail
);
1224 c
->lumPixBuf
[i
] = c
->lumPixBuf
[i
+ c
->vLumBufSize
];
1226 // 64 / (c->dstBpc & ~7) is the same as 16 / sizeof(scaling_intermediate)
1227 c
->uv_off_px
= dst_stride_px
+ 64 / (c
->dstBpc
& ~7);
1228 c
->uv_off_byte
= dst_stride
+ 16;
1229 for (i
= 0; i
< c
->vChrBufSize
; i
++) {
1230 FF_ALLOC_OR_GOTO(c
, c
->chrUPixBuf
[i
+ c
->vChrBufSize
],
1231 dst_stride
* 2 + 32, fail
);
1232 c
->chrUPixBuf
[i
] = c
->chrUPixBuf
[i
+ c
->vChrBufSize
];
1233 c
->chrVPixBuf
[i
] = c
->chrVPixBuf
[i
+ c
->vChrBufSize
]
1234 = c
->chrUPixBuf
[i
] + (dst_stride
>> 1) + 8;
1236 if (CONFIG_SWSCALE_ALPHA
&& c
->alpPixBuf
)
1237 for (i
= 0; i
< c
->vLumBufSize
; i
++) {
1238 FF_ALLOCZ_OR_GOTO(c
, c
->alpPixBuf
[i
+ c
->vLumBufSize
],
1239 dst_stride
+ 16, fail
);
1240 c
->alpPixBuf
[i
] = c
->alpPixBuf
[i
+ c
->vLumBufSize
];
1243 // try to avoid drawing green stuff between the right end and the stride end
1244 for (i
= 0; i
< c
->vChrBufSize
; i
++)
1245 memset(c
->chrUPixBuf
[i
], 64, dst_stride
* 2 + 1);
1247 assert(c
->chrDstH
<= dstH
);
1249 if (flags
& SWS_PRINT_INFO
) {
1250 if (flags
& SWS_FAST_BILINEAR
)
1251 av_log(c
, AV_LOG_INFO
, "FAST_BILINEAR scaler, ");
1252 else if (flags
& SWS_BILINEAR
)
1253 av_log(c
, AV_LOG_INFO
, "BILINEAR scaler, ");
1254 else if (flags
& SWS_BICUBIC
)
1255 av_log(c
, AV_LOG_INFO
, "BICUBIC scaler, ");
1256 else if (flags
& SWS_X
)
1257 av_log(c
, AV_LOG_INFO
, "Experimental scaler, ");
1258 else if (flags
& SWS_POINT
)
1259 av_log(c
, AV_LOG_INFO
, "Nearest Neighbor / POINT scaler, ");
1260 else if (flags
& SWS_AREA
)
1261 av_log(c
, AV_LOG_INFO
, "Area Averaging scaler, ");
1262 else if (flags
& SWS_BICUBLIN
)
1263 av_log(c
, AV_LOG_INFO
, "luma BICUBIC / chroma BILINEAR scaler, ");
1264 else if (flags
& SWS_GAUSS
)
1265 av_log(c
, AV_LOG_INFO
, "Gaussian scaler, ");
1266 else if (flags
& SWS_SINC
)
1267 av_log(c
, AV_LOG_INFO
, "Sinc scaler, ");
1268 else if (flags
& SWS_LANCZOS
)
1269 av_log(c
, AV_LOG_INFO
, "Lanczos scaler, ");
1270 else if (flags
& SWS_SPLINE
)
1271 av_log(c
, AV_LOG_INFO
, "Bicubic spline scaler, ");
1273 av_log(c
, AV_LOG_INFO
, "ehh flags invalid?! ");
1275 av_log(c
, AV_LOG_INFO
, "from %s to %s%s ",
1276 sws_format_name(srcFormat
),
1278 dstFormat
== AV_PIX_FMT_BGR555
|| dstFormat
== AV_PIX_FMT_BGR565
||
1279 dstFormat
== AV_PIX_FMT_RGB444BE
|| dstFormat
== AV_PIX_FMT_RGB444LE
||
1280 dstFormat
== AV_PIX_FMT_BGR444BE
|| dstFormat
== AV_PIX_FMT_BGR444LE ?
1285 sws_format_name(dstFormat
));
1287 if (INLINE_MMXEXT(cpu_flags
))
1288 av_log(c
, AV_LOG_INFO
, "using MMXEXT\n");
1289 else if (INLINE_AMD3DNOW(cpu_flags
))
1290 av_log(c
, AV_LOG_INFO
, "using 3DNOW\n");
1291 else if (INLINE_MMX(cpu_flags
))
1292 av_log(c
, AV_LOG_INFO
, "using MMX\n");
1293 else if (PPC_ALTIVEC(cpu_flags
))
1294 av_log(c
, AV_LOG_INFO
, "using AltiVec\n");
1296 av_log(c
, AV_LOG_INFO
, "using C\n");
1298 av_log(c
, AV_LOG_VERBOSE
, "%dx%d -> %dx%d\n", srcW
, srcH
, dstW
, dstH
);
1299 av_log(c
, AV_LOG_DEBUG
,
1300 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1301 c
->srcW
, c
->srcH
, c
->dstW
, c
->dstH
, c
->lumXInc
, c
->lumYInc
);
1302 av_log(c
, AV_LOG_DEBUG
,
1303 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
1304 c
->chrSrcW
, c
->chrSrcH
, c
->chrDstW
, c
->chrDstH
,
1305 c
->chrXInc
, c
->chrYInc
);
1308 c
->swscale
= ff_getSwsFunc(c
);
1310 fail
: // FIXME replace things by appropriate error codes
1314 #if FF_API_SWS_GETCONTEXT
1315 SwsContext
*sws_getContext(int srcW
, int srcH
, enum AVPixelFormat srcFormat
,
1316 int dstW
, int dstH
, enum AVPixelFormat dstFormat
,
1317 int flags
, SwsFilter
*srcFilter
,
1318 SwsFilter
*dstFilter
, const double *param
)
1322 if (!(c
= sws_alloc_context()))
1330 c
->srcRange
= handle_jpeg(&srcFormat
);
1331 c
->dstRange
= handle_jpeg(&dstFormat
);
1332 c
->srcFormat
= srcFormat
;
1333 c
->dstFormat
= dstFormat
;
1336 c
->param
[0] = param
[0];
1337 c
->param
[1] = param
[1];
1339 sws_setColorspaceDetails(c
, ff_yuv2rgb_coeffs
[SWS_CS_DEFAULT
], c
->srcRange
,
1340 ff_yuv2rgb_coeffs
[SWS_CS_DEFAULT
] /* FIXME*/,
1341 c
->dstRange
, 0, 1 << 16, 1 << 16);
1343 if (sws_init_context(c
, srcFilter
, dstFilter
) < 0) {
1352 SwsFilter
*sws_getDefaultFilter(float lumaGBlur
, float chromaGBlur
,
1353 float lumaSharpen
, float chromaSharpen
,
1354 float chromaHShift
, float chromaVShift
,
1357 SwsFilter
*filter
= av_malloc(sizeof(SwsFilter
));
1361 if (lumaGBlur
!= 0.0) {
1362 filter
->lumH
= sws_getGaussianVec(lumaGBlur
, 3.0);
1363 filter
->lumV
= sws_getGaussianVec(lumaGBlur
, 3.0);
1365 filter
->lumH
= sws_getIdentityVec();
1366 filter
->lumV
= sws_getIdentityVec();
1369 if (chromaGBlur
!= 0.0) {
1370 filter
->chrH
= sws_getGaussianVec(chromaGBlur
, 3.0);
1371 filter
->chrV
= sws_getGaussianVec(chromaGBlur
, 3.0);
1373 filter
->chrH
= sws_getIdentityVec();
1374 filter
->chrV
= sws_getIdentityVec();
1377 if (chromaSharpen
!= 0.0) {
1378 SwsVector
*id
= sws_getIdentityVec();
1379 sws_scaleVec(filter
->chrH
, -chromaSharpen
);
1380 sws_scaleVec(filter
->chrV
, -chromaSharpen
);
1381 sws_addVec(filter
->chrH
, id
);
1382 sws_addVec(filter
->chrV
, id
);
1386 if (lumaSharpen
!= 0.0) {
1387 SwsVector
*id
= sws_getIdentityVec();
1388 sws_scaleVec(filter
->lumH
, -lumaSharpen
);
1389 sws_scaleVec(filter
->lumV
, -lumaSharpen
);
1390 sws_addVec(filter
->lumH
, id
);
1391 sws_addVec(filter
->lumV
, id
);
1395 if (chromaHShift
!= 0.0)
1396 sws_shiftVec(filter
->chrH
, (int)(chromaHShift
+ 0.5));
1398 if (chromaVShift
!= 0.0)
1399 sws_shiftVec(filter
->chrV
, (int)(chromaVShift
+ 0.5));
1401 sws_normalizeVec(filter
->chrH
, 1.0);
1402 sws_normalizeVec(filter
->chrV
, 1.0);
1403 sws_normalizeVec(filter
->lumH
, 1.0);
1404 sws_normalizeVec(filter
->lumV
, 1.0);
1407 sws_printVec2(filter
->chrH
, NULL
, AV_LOG_DEBUG
);
1409 sws_printVec2(filter
->lumH
, NULL
, AV_LOG_DEBUG
);
1414 SwsVector
*sws_allocVec(int length
)
1416 SwsVector
*vec
= av_malloc(sizeof(SwsVector
));
1419 vec
->length
= length
;
1420 vec
->coeff
= av_malloc(sizeof(double) * length
);
1426 SwsVector
*sws_getGaussianVec(double variance
, double quality
)
1428 const int length
= (int)(variance
* quality
+ 0.5) | 1;
1430 double middle
= (length
- 1) * 0.5;
1431 SwsVector
*vec
= sws_allocVec(length
);
1436 for (i
= 0; i
< length
; i
++) {
1437 double dist
= i
- middle
;
1438 vec
->coeff
[i
] = exp(-dist
* dist
/ (2 * variance
* variance
)) /
1439 sqrt(2 * variance
* M_PI
);
1442 sws_normalizeVec(vec
, 1.0);
1447 SwsVector
*sws_getConstVec(double c
, int length
)
1450 SwsVector
*vec
= sws_allocVec(length
);
1455 for (i
= 0; i
< length
; i
++)
1461 SwsVector
*sws_getIdentityVec(void)
1463 return sws_getConstVec(1.0, 1);
1466 static double sws_dcVec(SwsVector
*a
)
1471 for (i
= 0; i
< a
->length
; i
++)
1477 void sws_scaleVec(SwsVector
*a
, double scalar
)
1481 for (i
= 0; i
< a
->length
; i
++)
1482 a
->coeff
[i
] *= scalar
;
1485 void sws_normalizeVec(SwsVector
*a
, double height
)
1487 sws_scaleVec(a
, height
/ sws_dcVec(a
));
1490 static SwsVector
*sws_getConvVec(SwsVector
*a
, SwsVector
*b
)
1492 int length
= a
->length
+ b
->length
- 1;
1494 SwsVector
*vec
= sws_getConstVec(0.0, length
);
1499 for (i
= 0; i
< a
->length
; i
++) {
1500 for (j
= 0; j
< b
->length
; j
++) {
1501 vec
->coeff
[i
+ j
] += a
->coeff
[i
] * b
->coeff
[j
];
1508 static SwsVector
*sws_sumVec(SwsVector
*a
, SwsVector
*b
)
1510 int length
= FFMAX(a
->length
, b
->length
);
1512 SwsVector
*vec
= sws_getConstVec(0.0, length
);
1517 for (i
= 0; i
< a
->length
; i
++)
1518 vec
->coeff
[i
+ (length
- 1) / 2 - (a
->length
- 1) / 2] += a
->coeff
[i
];
1519 for (i
= 0; i
< b
->length
; i
++)
1520 vec
->coeff
[i
+ (length
- 1) / 2 - (b
->length
- 1) / 2] += b
->coeff
[i
];
1525 static SwsVector
*sws_diffVec(SwsVector
*a
, SwsVector
*b
)
1527 int length
= FFMAX(a
->length
, b
->length
);
1529 SwsVector
*vec
= sws_getConstVec(0.0, length
);
1534 for (i
= 0; i
< a
->length
; i
++)
1535 vec
->coeff
[i
+ (length
- 1) / 2 - (a
->length
- 1) / 2] += a
->coeff
[i
];
1536 for (i
= 0; i
< b
->length
; i
++)
1537 vec
->coeff
[i
+ (length
- 1) / 2 - (b
->length
- 1) / 2] -= b
->coeff
[i
];
1542 /* shift left / or right if "shift" is negative */
1543 static SwsVector
*sws_getShiftedVec(SwsVector
*a
, int shift
)
1545 int length
= a
->length
+ FFABS(shift
) * 2;
1547 SwsVector
*vec
= sws_getConstVec(0.0, length
);
1552 for (i
= 0; i
< a
->length
; i
++) {
1553 vec
->coeff
[i
+ (length
- 1) / 2 -
1554 (a
->length
- 1) / 2 - shift
] = a
->coeff
[i
];
1560 void sws_shiftVec(SwsVector
*a
, int shift
)
1562 SwsVector
*shifted
= sws_getShiftedVec(a
, shift
);
1564 a
->coeff
= shifted
->coeff
;
1565 a
->length
= shifted
->length
;
1569 void sws_addVec(SwsVector
*a
, SwsVector
*b
)
1571 SwsVector
*sum
= sws_sumVec(a
, b
);
1573 a
->coeff
= sum
->coeff
;
1574 a
->length
= sum
->length
;
1578 void sws_subVec(SwsVector
*a
, SwsVector
*b
)
1580 SwsVector
*diff
= sws_diffVec(a
, b
);
1582 a
->coeff
= diff
->coeff
;
1583 a
->length
= diff
->length
;
1587 void sws_convVec(SwsVector
*a
, SwsVector
*b
)
1589 SwsVector
*conv
= sws_getConvVec(a
, b
);
1591 a
->coeff
= conv
->coeff
;
1592 a
->length
= conv
->length
;
1596 SwsVector
*sws_cloneVec(SwsVector
*a
)
1599 SwsVector
*vec
= sws_allocVec(a
->length
);
1604 for (i
= 0; i
< a
->length
; i
++)
1605 vec
->coeff
[i
] = a
->coeff
[i
];
1610 void sws_printVec2(SwsVector
*a
, AVClass
*log_ctx
, int log_level
)
1617 for (i
= 0; i
< a
->length
; i
++)
1618 if (a
->coeff
[i
] > max
)
1621 for (i
= 0; i
< a
->length
; i
++)
1622 if (a
->coeff
[i
] < min
)
1627 for (i
= 0; i
< a
->length
; i
++) {
1628 int x
= (int)((a
->coeff
[i
] - min
) * 60.0 / range
+ 0.5);
1629 av_log(log_ctx
, log_level
, "%1.3f ", a
->coeff
[i
]);
1631 av_log(log_ctx
, log_level
, " ");
1632 av_log(log_ctx
, log_level
, "|\n");
1636 void sws_freeVec(SwsVector
*a
)
1640 av_freep(&a
->coeff
);
1645 void sws_freeFilter(SwsFilter
*filter
)
1651 sws_freeVec(filter
->lumH
);
1653 sws_freeVec(filter
->lumV
);
1655 sws_freeVec(filter
->chrH
);
1657 sws_freeVec(filter
->chrV
);
1661 void sws_freeContext(SwsContext
*c
)
1668 for (i
= 0; i
< c
->vLumBufSize
; i
++)
1669 av_freep(&c
->lumPixBuf
[i
]);
1670 av_freep(&c
->lumPixBuf
);
1673 if (c
->chrUPixBuf
) {
1674 for (i
= 0; i
< c
->vChrBufSize
; i
++)
1675 av_freep(&c
->chrUPixBuf
[i
]);
1676 av_freep(&c
->chrUPixBuf
);
1677 av_freep(&c
->chrVPixBuf
);
1680 if (CONFIG_SWSCALE_ALPHA
&& c
->alpPixBuf
) {
1681 for (i
= 0; i
< c
->vLumBufSize
; i
++)
1682 av_freep(&c
->alpPixBuf
[i
]);
1683 av_freep(&c
->alpPixBuf
);
1686 av_freep(&c
->vLumFilter
);
1687 av_freep(&c
->vChrFilter
);
1688 av_freep(&c
->hLumFilter
);
1689 av_freep(&c
->hChrFilter
);
1691 av_freep(&c
->vYCoeffsBank
);
1692 av_freep(&c
->vCCoeffsBank
);
1695 av_freep(&c
->vLumFilterPos
);
1696 av_freep(&c
->vChrFilterPos
);
1697 av_freep(&c
->hLumFilterPos
);
1698 av_freep(&c
->hChrFilterPos
);
1702 if (c
->lumMmxextFilterCode
)
1703 munmap(c
->lumMmxextFilterCode
, c
->lumMmxextFilterCodeSize
);
1704 if (c
->chrMmxextFilterCode
)
1705 munmap(c
->chrMmxextFilterCode
, c
->chrMmxextFilterCodeSize
);
1706 #elif HAVE_VIRTUALALLOC
1707 if (c
->lumMmxextFilterCode
)
1708 VirtualFree(c
->lumMmxextFilterCode
, 0, MEM_RELEASE
);
1709 if (c
->chrMmxextFilterCode
)
1710 VirtualFree(c
->chrMmxextFilterCode
, 0, MEM_RELEASE
);
1712 av_free(c
->lumMmxextFilterCode
);
1713 av_free(c
->chrMmxextFilterCode
);
1715 c
->lumMmxextFilterCode
= NULL
;
1716 c
->chrMmxextFilterCode
= NULL
;
1717 #endif /* HAVE_MMX_INLINE */
1719 av_freep(&c
->yuvTable
);
1720 av_free(c
->formatConvBuffer
);
1725 struct SwsContext
*sws_getCachedContext(struct SwsContext
*context
, int srcW
,
1726 int srcH
, enum AVPixelFormat srcFormat
,
1728 enum AVPixelFormat dstFormat
, int flags
,
1729 SwsFilter
*srcFilter
,
1730 SwsFilter
*dstFilter
,
1731 const double *param
)
1733 static const double default_param
[2] = { SWS_PARAM_DEFAULT
,
1734 SWS_PARAM_DEFAULT
};
1737 param
= default_param
;
1740 (context
->srcW
!= srcW
||
1741 context
->srcH
!= srcH
||
1742 context
->srcFormat
!= srcFormat
||
1743 context
->dstW
!= dstW
||
1744 context
->dstH
!= dstH
||
1745 context
->dstFormat
!= dstFormat
||
1746 context
->flags
!= flags
||
1747 context
->param
[0] != param
[0] ||
1748 context
->param
[1] != param
[1])) {
1749 sws_freeContext(context
);
1754 if (!(context
= sws_alloc_context()))
1756 context
->srcW
= srcW
;
1757 context
->srcH
= srcH
;
1758 context
->srcRange
= handle_jpeg(&srcFormat
);
1759 context
->srcFormat
= srcFormat
;
1760 context
->dstW
= dstW
;
1761 context
->dstH
= dstH
;
1762 context
->dstRange
= handle_jpeg(&dstFormat
);
1763 context
->dstFormat
= dstFormat
;
1764 context
->flags
= flags
;
1765 context
->param
[0] = param
[0];
1766 context
->param
[1] = param
[1];
1767 sws_setColorspaceDetails(context
, ff_yuv2rgb_coeffs
[SWS_CS_DEFAULT
],
1769 ff_yuv2rgb_coeffs
[SWS_CS_DEFAULT
] /* FIXME*/,
1770 context
->dstRange
, 0, 1 << 16, 1 << 16);
1771 if (sws_init_context(context
, srcFilter
, dstFilter
) < 0) {
1772 sws_freeContext(context
);