]> git.sesse.net Git - ffmpeg/blob - libswscale/swscale.c
swscale: fix overflows in output of RGB48 pixels.
[ffmpeg] / libswscale / swscale.c
1 /*
2  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of Libav.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /*
22   supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR32_1, BGR24, BGR16, BGR15, RGB32, RGB32_1, RGB24, Y8/Y800, YVU9/IF09, PAL8
23   supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09
24   {BGR,RGB}{1,4,8,15,16} support dithering
25
26   unscaled special converters (YV12=I420=IYUV, Y800=Y8)
27   YV12 -> {BGR,RGB}{1,4,8,12,15,16,24,32}
28   x -> x
29   YUV9 -> YV12
30   YUV9/YV12 -> Y800
31   Y800 -> YUV9/YV12
32   BGR24 -> BGR32 & RGB24 -> RGB32
33   BGR32 -> BGR24 & RGB32 -> RGB24
34   BGR15 -> BGR16
35 */
36
37 /*
38 tested special converters (most are tested actually, but I did not write it down ...)
39  YV12 -> BGR12/BGR16
40  YV12 -> YV12
41  BGR15 -> BGR16
42  BGR16 -> BGR16
43  YVU9 -> YV12
44
45 untested special converters
46   YV12/I420 -> BGR15/BGR24/BGR32 (it is the yuv2rgb stuff, so it should be OK)
47   YV12/I420 -> YV12/I420
48   YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format
49   BGR24 -> BGR32 & RGB24 -> RGB32
50   BGR32 -> BGR24 & RGB32 -> RGB24
51   BGR24 -> YV12
52 */
53
54 #include <inttypes.h>
55 #include <string.h>
56 #include <math.h>
57 #include <stdio.h>
58 #include "config.h"
59 #include <assert.h>
60 #include "swscale.h"
61 #include "swscale_internal.h"
62 #include "rgb2rgb.h"
63 #include "libavutil/intreadwrite.h"
64 #include "libavutil/cpu.h"
65 #include "libavutil/avutil.h"
66 #include "libavutil/mathematics.h"
67 #include "libavutil/bswap.h"
68 #include "libavutil/pixdesc.h"
69
70 #define DITHER1XBPP
71
72 #define RGB2YUV_SHIFT 15
73 #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
74 #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
75 #define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
76 #define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5))
77 #define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5))
78 #define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5))
79 #define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5))
80 #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
81 #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
82
83 /*
84 NOTES
85 Special versions: fast Y 1:1 scaling (no interpolation in y direction)
86
87 TODO
88 more intelligent misalignment avoidance for the horizontal scaler
89 write special vertical cubic upscale version
90 optimize C code (YV12 / minmax)
91 add support for packed pixel YUV input & output
92 add support for Y8 output
93 optimize BGR24 & BGR32
94 add BGR4 output support
95 write special BGR->BGR scaler
96 */
97
98 DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_4)[2][8]={
99 {  1,   3,   1,   3,   1,   3,   1,   3, },
100 {  2,   0,   2,   0,   2,   0,   2,   0, },
101 };
102
103 DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_8)[2][8]={
104 {  6,   2,   6,   2,   6,   2,   6,   2, },
105 {  0,   4,   0,   4,   0,   4,   0,   4, },
106 };
107
108 DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[4][8]={
109 {  8,   4,  11,   7,   8,   4,  11,   7, },
110 {  2,  14,   1,  13,   2,  14,   1,  13, },
111 { 10,   6,   9,   5,  10,   6,   9,   5, },
112 {  0,  12,   3,  15,   0,  12,   3,  15, },
113 };
114
115 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={
116 { 17,   9,  23,  15,  16,   8,  22,  14, },
117 {  5,  29,   3,  27,   4,  28,   2,  26, },
118 { 21,  13,  19,  11,  20,  12,  18,  10, },
119 {  0,  24,   6,  30,   1,  25,   7,  31, },
120 { 16,   8,  22,  14,  17,   9,  23,  15, },
121 {  4,  28,   2,  26,   5,  29,   3,  27, },
122 { 20,  12,  18,  10,  21,  13,  19,  11, },
123 {  1,  25,   7,  31,   0,  24,   6,  30, },
124 };
125
126 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[8][8]={
127 {  0,  55,  14,  68,   3,  58,  17,  72, },
128 { 37,  18,  50,  32,  40,  22,  54,  35, },
129 {  9,  64,   5,  59,  13,  67,   8,  63, },
130 { 46,  27,  41,  23,  49,  31,  44,  26, },
131 {  2,  57,  16,  71,   1,  56,  15,  70, },
132 { 39,  21,  52,  34,  38,  19,  51,  33, },
133 { 11,  66,   7,  62,  10,  65,   6,  60, },
134 { 48,  30,  43,  25,  47,  29,  42,  24, },
135 };
136
137 #if 1
138 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
139 {117,  62, 158, 103, 113,  58, 155, 100, },
140 { 34, 199,  21, 186,  31, 196,  17, 182, },
141 {144,  89, 131,  76, 141,  86, 127,  72, },
142 {  0, 165,  41, 206,  10, 175,  52, 217, },
143 {110,  55, 151,  96, 120,  65, 162, 107, },
144 { 28, 193,  14, 179,  38, 203,  24, 189, },
145 {138,  83, 124,  69, 148,  93, 134,  79, },
146 {  7, 172,  48, 213,   3, 168,  45, 210, },
147 };
148 #elif 1
149 // tries to correct a gamma of 1.5
150 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
151 {  0, 143,  18, 200,   2, 156,  25, 215, },
152 { 78,  28, 125,  64,  89,  36, 138,  74, },
153 { 10, 180,   3, 161,  16, 195,   8, 175, },
154 {109,  51,  93,  38, 121,  60, 105,  47, },
155 {  1, 152,  23, 210,   0, 147,  20, 205, },
156 { 85,  33, 134,  71,  81,  30, 130,  67, },
157 { 14, 190,   6, 171,  12, 185,   5, 166, },
158 {117,  57, 101,  44, 113,  54,  97,  41, },
159 };
160 #elif 1
161 // tries to correct a gamma of 2.0
162 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
163 {  0, 124,   8, 193,   0, 140,  12, 213, },
164 { 55,  14, 104,  42,  66,  19, 119,  52, },
165 {  3, 168,   1, 145,   6, 187,   3, 162, },
166 { 86,  31,  70,  21,  99,  39,  82,  28, },
167 {  0, 134,  11, 206,   0, 129,   9, 200, },
168 { 62,  17, 114,  48,  58,  16, 109,  45, },
169 {  5, 181,   2, 157,   4, 175,   1, 151, },
170 { 95,  36,  78,  26,  90,  34,  74,  24, },
171 };
172 #else
173 // tries to correct a gamma of 2.5
174 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
175 {  0, 107,   3, 187,   0, 125,   6, 212, },
176 { 39,   7,  86,  28,  49,  11, 102,  36, },
177 {  1, 158,   0, 131,   3, 180,   1, 151, },
178 { 68,  19,  52,  12,  81,  25,  64,  17, },
179 {  0, 119,   5, 203,   0, 113,   4, 195, },
180 { 45,   9,  96,  33,  42,   8,  91,  30, },
181 {  2, 172,   1, 144,   2, 165,   0, 137, },
182 { 77,  23,  60,  15,  72,  21,  56,  14, },
183 };
184 #endif
185 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_128)[8][8] = {
186 {  36, 68, 60, 92, 34, 66, 58, 90,},
187 { 100,  4,124, 28, 98,  2,122, 26,},
188 {  52, 84, 44, 76, 50, 82, 42, 74,},
189 { 116, 20,108, 12,114, 18,106, 10,},
190 {  32, 64, 56, 88, 38, 70, 62, 94,},
191 {  96,  0,120, 24,102,  6,126, 30,},
192 {  48, 80, 40, 72, 54, 86, 46, 78,},
193 { 112, 16,104,  8,118, 22,110, 14,},
194 };
195 DECLARE_ALIGNED(8, const uint8_t, ff_sws_pb_64)[8] =
196 {  64, 64, 64, 64, 64, 64, 64, 64 };
197
198 #define output_pixel(pos, val, bias, signedness) \
199     if (big_endian) { \
200         AV_WB16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \
201     } else { \
202         AV_WL16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \
203     }
204
205 static av_always_inline void
206 yuv2plane1_16_c_template(const int32_t *src, uint16_t *dest, int dstW,
207                          int big_endian, int output_bits)
208 {
209     int i;
210     int shift = 19 - output_bits;
211
212     for (i = 0; i < dstW; i++) {
213         int val = src[i] + (1 << (shift - 1));
214         output_pixel(&dest[i], val, 0, uint);
215     }
216 }
217
218 static av_always_inline void
219 yuv2planeX_16_c_template(const int16_t *filter, int filterSize,
220                          const int32_t **src, uint16_t *dest, int dstW,
221                          int big_endian, int output_bits)
222 {
223     int i;
224     int shift = 15 + 16 - output_bits;
225
226     for (i = 0; i < dstW; i++) {
227         int val = 1 << (30-output_bits);
228         int j;
229
230         /* range of val is [0,0x7FFFFFFF], so 31 bits, but with lanczos/spline
231          * filters (or anything with negative coeffs, the range can be slightly
232          * wider in both directions. To account for this overflow, we subtract
233          * a constant so it always fits in the signed range (assuming a
234          * reasonable filterSize), and re-add that at the end. */
235         val -= 0x40000000;
236         for (j = 0; j < filterSize; j++)
237             val += src[j][i] * filter[j];
238
239         output_pixel(&dest[i], val, 0x8000, int);
240     }
241 }
242
243 #undef output_pixel
244
245 #define output_pixel(pos, val) \
246     if (big_endian) { \
247         AV_WB16(pos, av_clip_uintp2(val >> shift, output_bits)); \
248     } else { \
249         AV_WL16(pos, av_clip_uintp2(val >> shift, output_bits)); \
250     }
251
252 static av_always_inline void
253 yuv2plane1_10_c_template(const int16_t *src, uint16_t *dest, int dstW,
254                          int big_endian, int output_bits)
255 {
256     int i;
257     int shift = 15 - output_bits;
258
259     for (i = 0; i < dstW; i++) {
260         int val = src[i] + (1 << (shift - 1));
261         output_pixel(&dest[i], val);
262     }
263 }
264
265 static av_always_inline void
266 yuv2planeX_10_c_template(const int16_t *filter, int filterSize,
267                          const int16_t **src, uint16_t *dest, int dstW,
268                          int big_endian, int output_bits)
269 {
270     int i;
271     int shift = 11 + 16 - output_bits;
272
273     for (i = 0; i < dstW; i++) {
274         int val = 1 << (26-output_bits);
275         int j;
276
277         for (j = 0; j < filterSize; j++)
278             val += src[j][i] * filter[j];
279
280         output_pixel(&dest[i], val);
281     }
282 }
283
284 #undef output_pixel
285
286 #define yuv2NBPS(bits, BE_LE, is_be, template_size, typeX_t) \
287 static void yuv2plane1_ ## bits ## BE_LE ## _c(const int16_t *src, \
288                               uint8_t *dest, int dstW, \
289                               const uint8_t *dither, int offset)\
290 { \
291     yuv2plane1_ ## template_size ## _c_template((const typeX_t *) src, \
292                          (uint16_t *) dest, dstW, is_be, bits); \
293 }\
294 static void yuv2planeX_ ## bits ## BE_LE ## _c(const int16_t *filter, int filterSize, \
295                               const int16_t **src, uint8_t *dest, int dstW, \
296                               const uint8_t *dither, int offset)\
297 { \
298     yuv2planeX_## template_size ## _c_template(filter, \
299                          filterSize, (const typeX_t **) src, \
300                          (uint16_t *) dest, dstW, is_be, bits); \
301 }
302 yuv2NBPS( 9, BE, 1, 10, int16_t)
303 yuv2NBPS( 9, LE, 0, 10, int16_t)
304 yuv2NBPS(10, BE, 1, 10, int16_t)
305 yuv2NBPS(10, LE, 0, 10, int16_t)
306 yuv2NBPS(16, BE, 1, 16, int32_t)
307 yuv2NBPS(16, LE, 0, 16, int32_t)
308
309 static void yuv2planeX_8_c(const int16_t *filter, int filterSize,
310                            const int16_t **src, uint8_t *dest, int dstW,
311                            const uint8_t *dither, int offset)
312 {
313     int i;
314     for (i=0; i<dstW; i++) {
315         int val = dither[(i + offset) & 7] << 12;
316         int j;
317         for (j=0; j<filterSize; j++)
318             val += src[j][i] * filter[j];
319
320         dest[i]= av_clip_uint8(val>>19);
321     }
322 }
323
324 static void yuv2plane1_8_c(const int16_t *src, uint8_t *dest, int dstW,
325                            const uint8_t *dither, int offset)
326 {
327     int i;
328     for (i=0; i<dstW; i++) {
329         int val = (src[i] + dither[(i + offset) & 7]) >> 7;
330         dest[i]= av_clip_uint8(val);
331     }
332 }
333
334 static void yuv2nv12cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize,
335                         const int16_t **chrUSrc, const int16_t **chrVSrc,
336                         uint8_t *dest, int chrDstW)
337 {
338     enum PixelFormat dstFormat = c->dstFormat;
339     const uint8_t *chrDither = c->chrDither8;
340     int i;
341
342     if (dstFormat == PIX_FMT_NV12)
343         for (i=0; i<chrDstW; i++) {
344             int u = chrDither[i & 7] << 12;
345             int v = chrDither[(i + 3) & 7] << 12;
346             int j;
347             for (j=0; j<chrFilterSize; j++) {
348                 u += chrUSrc[j][i] * chrFilter[j];
349                 v += chrVSrc[j][i] * chrFilter[j];
350             }
351
352             dest[2*i]= av_clip_uint8(u>>19);
353             dest[2*i+1]= av_clip_uint8(v>>19);
354         }
355     else
356         for (i=0; i<chrDstW; i++) {
357             int u = chrDither[i & 7] << 12;
358             int v = chrDither[(i + 3) & 7] << 12;
359             int j;
360             for (j=0; j<chrFilterSize; j++) {
361                 u += chrUSrc[j][i] * chrFilter[j];
362                 v += chrVSrc[j][i] * chrFilter[j];
363             }
364
365             dest[2*i]= av_clip_uint8(v>>19);
366             dest[2*i+1]= av_clip_uint8(u>>19);
367         }
368 }
369
370 #define output_pixel(pos, val) \
371         if (target == PIX_FMT_GRAY16BE) { \
372             AV_WB16(pos, val); \
373         } else { \
374             AV_WL16(pos, val); \
375         }
376
377 static av_always_inline void
378 yuv2gray16_X_c_template(SwsContext *c, const int16_t *lumFilter,
379                         const int32_t **lumSrc, int lumFilterSize,
380                         const int16_t *chrFilter, const int32_t **chrUSrc,
381                         const int32_t **chrVSrc, int chrFilterSize,
382                         const int32_t **alpSrc, uint16_t *dest, int dstW,
383                         int y, enum PixelFormat target)
384 {
385     int i;
386
387     for (i = 0; i < (dstW >> 1); i++) {
388         int j;
389         int Y1 = 1 << 14;
390         int Y2 = 1 << 14;
391
392         for (j = 0; j < lumFilterSize; j++) {
393             Y1 += lumSrc[j][i * 2]     * lumFilter[j];
394             Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
395         }
396         Y1 >>= 15;
397         Y2 >>= 15;
398         if ((Y1 | Y2) & 0x10000) {
399             Y1 = av_clip_uint16(Y1);
400             Y2 = av_clip_uint16(Y2);
401         }
402         output_pixel(&dest[i * 2 + 0], Y1);
403         output_pixel(&dest[i * 2 + 1], Y2);
404     }
405 }
406
407 static av_always_inline void
408 yuv2gray16_2_c_template(SwsContext *c, const int32_t *buf[2],
409                         const int32_t *ubuf[2], const int32_t *vbuf[2],
410                         const int32_t *abuf[2], uint16_t *dest, int dstW,
411                         int yalpha, int uvalpha, int y,
412                         enum PixelFormat target)
413 {
414     int  yalpha1 = 4095 - yalpha;
415     int i;
416     const int32_t *buf0 = buf[0], *buf1 = buf[1];
417
418     for (i = 0; i < (dstW >> 1); i++) {
419         int Y1 = (buf0[i * 2    ] * yalpha1 + buf1[i * 2    ] * yalpha) >> 15;
420         int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 15;
421
422         output_pixel(&dest[i * 2 + 0], Y1);
423         output_pixel(&dest[i * 2 + 1], Y2);
424     }
425 }
426
427 static av_always_inline void
428 yuv2gray16_1_c_template(SwsContext *c, const int32_t *buf0,
429                         const int32_t *ubuf[2], const int32_t *vbuf[2],
430                         const int32_t *abuf0, uint16_t *dest, int dstW,
431                         int uvalpha, int y, enum PixelFormat target)
432 {
433     int i;
434
435     for (i = 0; i < (dstW >> 1); i++) {
436         int Y1 = buf0[i * 2    ] << 1;
437         int Y2 = buf0[i * 2 + 1] << 1;
438
439         output_pixel(&dest[i * 2 + 0], Y1);
440         output_pixel(&dest[i * 2 + 1], Y2);
441     }
442 }
443
444 #undef output_pixel
445
446 #define YUV2PACKED16WRAPPER(name, base, ext, fmt) \
447 static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
448                         const int16_t **_lumSrc, int lumFilterSize, \
449                         const int16_t *chrFilter, const int16_t **_chrUSrc, \
450                         const int16_t **_chrVSrc, int chrFilterSize, \
451                         const int16_t **_alpSrc, uint8_t *_dest, int dstW, \
452                         int y) \
453 { \
454     const int32_t **lumSrc  = (const int32_t **) _lumSrc, \
455                   **chrUSrc = (const int32_t **) _chrUSrc, \
456                   **chrVSrc = (const int32_t **) _chrVSrc, \
457                   **alpSrc  = (const int32_t **) _alpSrc; \
458     uint16_t *dest = (uint16_t *) _dest; \
459     name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
460                           chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
461                           alpSrc, dest, dstW, y, fmt); \
462 } \
463  \
464 static void name ## ext ## _2_c(SwsContext *c, const int16_t *_buf[2], \
465                         const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
466                         const int16_t *_abuf[2], uint8_t *_dest, int dstW, \
467                         int yalpha, int uvalpha, int y) \
468 { \
469     const int32_t **buf  = (const int32_t **) _buf, \
470                   **ubuf = (const int32_t **) _ubuf, \
471                   **vbuf = (const int32_t **) _vbuf, \
472                   **abuf = (const int32_t **) _abuf; \
473     uint16_t *dest = (uint16_t *) _dest; \
474     name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
475                           dest, dstW, yalpha, uvalpha, y, fmt); \
476 } \
477  \
478 static void name ## ext ## _1_c(SwsContext *c, const int16_t *_buf0, \
479                         const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
480                         const int16_t *_abuf0, uint8_t *_dest, int dstW, \
481                         int uvalpha, int y) \
482 { \
483     const int32_t *buf0  = (const int32_t *)  _buf0, \
484                  **ubuf  = (const int32_t **) _ubuf, \
485                  **vbuf  = (const int32_t **) _vbuf, \
486                   *abuf0 = (const int32_t *)  _abuf0; \
487     uint16_t *dest = (uint16_t *) _dest; \
488     name ## base ## _1_c_template(c, buf0, ubuf, vbuf, abuf0, dest, \
489                                   dstW, uvalpha, y, fmt); \
490 }
491
492 YUV2PACKED16WRAPPER(yuv2gray16,, LE, PIX_FMT_GRAY16LE)
493 YUV2PACKED16WRAPPER(yuv2gray16,, BE, PIX_FMT_GRAY16BE)
494
495 #define output_pixel(pos, acc) \
496     if (target == PIX_FMT_MONOBLACK) { \
497         pos = acc; \
498     } else { \
499         pos = ~acc; \
500     }
501
502 static av_always_inline void
503 yuv2mono_X_c_template(SwsContext *c, const int16_t *lumFilter,
504                       const int16_t **lumSrc, int lumFilterSize,
505                       const int16_t *chrFilter, const int16_t **chrUSrc,
506                       const int16_t **chrVSrc, int chrFilterSize,
507                       const int16_t **alpSrc, uint8_t *dest, int dstW,
508                       int y, enum PixelFormat target)
509 {
510     const uint8_t * const d128=dither_8x8_220[y&7];
511     uint8_t *g = c->table_gU[128] + c->table_gV[128];
512     int i;
513     unsigned acc = 0;
514
515     for (i = 0; i < dstW - 1; i += 2) {
516         int j;
517         int Y1 = 1 << 18;
518         int Y2 = 1 << 18;
519
520         for (j = 0; j < lumFilterSize; j++) {
521             Y1 += lumSrc[j][i]   * lumFilter[j];
522             Y2 += lumSrc[j][i+1] * lumFilter[j];
523         }
524         Y1 >>= 19;
525         Y2 >>= 19;
526         if ((Y1 | Y2) & 0x100) {
527             Y1 = av_clip_uint8(Y1);
528             Y2 = av_clip_uint8(Y2);
529         }
530         acc += acc + g[Y1 + d128[(i + 0) & 7]];
531         acc += acc + g[Y2 + d128[(i + 1) & 7]];
532         if ((i & 7) == 6) {
533             output_pixel(*dest++, acc);
534         }
535     }
536 }
537
538 static av_always_inline void
539 yuv2mono_2_c_template(SwsContext *c, const int16_t *buf[2],
540                       const int16_t *ubuf[2], const int16_t *vbuf[2],
541                       const int16_t *abuf[2], uint8_t *dest, int dstW,
542                       int yalpha, int uvalpha, int y,
543                       enum PixelFormat target)
544 {
545     const int16_t *buf0  = buf[0],  *buf1  = buf[1];
546     const uint8_t * const d128 = dither_8x8_220[y & 7];
547     uint8_t *g = c->table_gU[128] + c->table_gV[128];
548     int  yalpha1 = 4095 - yalpha;
549     int i;
550
551     for (i = 0; i < dstW - 7; i += 8) {
552         int acc =    g[((buf0[i    ] * yalpha1 + buf1[i    ] * yalpha) >> 19) + d128[0]];
553         acc += acc + g[((buf0[i + 1] * yalpha1 + buf1[i + 1] * yalpha) >> 19) + d128[1]];
554         acc += acc + g[((buf0[i + 2] * yalpha1 + buf1[i + 2] * yalpha) >> 19) + d128[2]];
555         acc += acc + g[((buf0[i + 3] * yalpha1 + buf1[i + 3] * yalpha) >> 19) + d128[3]];
556         acc += acc + g[((buf0[i + 4] * yalpha1 + buf1[i + 4] * yalpha) >> 19) + d128[4]];
557         acc += acc + g[((buf0[i + 5] * yalpha1 + buf1[i + 5] * yalpha) >> 19) + d128[5]];
558         acc += acc + g[((buf0[i + 6] * yalpha1 + buf1[i + 6] * yalpha) >> 19) + d128[6]];
559         acc += acc + g[((buf0[i + 7] * yalpha1 + buf1[i + 7] * yalpha) >> 19) + d128[7]];
560         output_pixel(*dest++, acc);
561     }
562 }
563
564 static av_always_inline void
565 yuv2mono_1_c_template(SwsContext *c, const int16_t *buf0,
566                       const int16_t *ubuf[2], const int16_t *vbuf[2],
567                       const int16_t *abuf0, uint8_t *dest, int dstW,
568                       int uvalpha, int y, enum PixelFormat target)
569 {
570     const uint8_t * const d128 = dither_8x8_220[y & 7];
571     uint8_t *g = c->table_gU[128] + c->table_gV[128];
572     int i;
573
574     for (i = 0; i < dstW - 7; i += 8) {
575         int acc =    g[(buf0[i    ] >> 7) + d128[0]];
576         acc += acc + g[(buf0[i + 1] >> 7) + d128[1]];
577         acc += acc + g[(buf0[i + 2] >> 7) + d128[2]];
578         acc += acc + g[(buf0[i + 3] >> 7) + d128[3]];
579         acc += acc + g[(buf0[i + 4] >> 7) + d128[4]];
580         acc += acc + g[(buf0[i + 5] >> 7) + d128[5]];
581         acc += acc + g[(buf0[i + 6] >> 7) + d128[6]];
582         acc += acc + g[(buf0[i + 7] >> 7) + d128[7]];
583         output_pixel(*dest++, acc);
584     }
585 }
586
587 #undef output_pixel
588
589 #define YUV2PACKEDWRAPPER(name, base, ext, fmt) \
590 static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
591                                 const int16_t **lumSrc, int lumFilterSize, \
592                                 const int16_t *chrFilter, const int16_t **chrUSrc, \
593                                 const int16_t **chrVSrc, int chrFilterSize, \
594                                 const int16_t **alpSrc, uint8_t *dest, int dstW, \
595                                 int y) \
596 { \
597     name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
598                                   chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
599                                   alpSrc, dest, dstW, y, fmt); \
600 } \
601  \
602 static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
603                                 const int16_t *ubuf[2], const int16_t *vbuf[2], \
604                                 const int16_t *abuf[2], uint8_t *dest, int dstW, \
605                                 int yalpha, int uvalpha, int y) \
606 { \
607     name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
608                                   dest, dstW, yalpha, uvalpha, y, fmt); \
609 } \
610  \
611 static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
612                                 const int16_t *ubuf[2], const int16_t *vbuf[2], \
613                                 const int16_t *abuf0, uint8_t *dest, int dstW, \
614                                 int uvalpha, int y) \
615 { \
616     name ## base ## _1_c_template(c, buf0, ubuf, vbuf, \
617                                   abuf0, dest, dstW, uvalpha, \
618                                   y, fmt); \
619 }
620
621 YUV2PACKEDWRAPPER(yuv2mono,, white, PIX_FMT_MONOWHITE)
622 YUV2PACKEDWRAPPER(yuv2mono,, black, PIX_FMT_MONOBLACK)
623
624 #define output_pixels(pos, Y1, U, Y2, V) \
625     if (target == PIX_FMT_YUYV422) { \
626         dest[pos + 0] = Y1; \
627         dest[pos + 1] = U;  \
628         dest[pos + 2] = Y2; \
629         dest[pos + 3] = V;  \
630     } else { \
631         dest[pos + 0] = U;  \
632         dest[pos + 1] = Y1; \
633         dest[pos + 2] = V;  \
634         dest[pos + 3] = Y2; \
635     }
636
637 static av_always_inline void
638 yuv2422_X_c_template(SwsContext *c, const int16_t *lumFilter,
639                      const int16_t **lumSrc, int lumFilterSize,
640                      const int16_t *chrFilter, const int16_t **chrUSrc,
641                      const int16_t **chrVSrc, int chrFilterSize,
642                      const int16_t **alpSrc, uint8_t *dest, int dstW,
643                      int y, enum PixelFormat target)
644 {
645     int i;
646
647     for (i = 0; i < (dstW >> 1); i++) {
648         int j;
649         int Y1 = 1 << 18;
650         int Y2 = 1 << 18;
651         int U  = 1 << 18;
652         int V  = 1 << 18;
653
654         for (j = 0; j < lumFilterSize; j++) {
655             Y1 += lumSrc[j][i * 2]     * lumFilter[j];
656             Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
657         }
658         for (j = 0; j < chrFilterSize; j++) {
659             U += chrUSrc[j][i] * chrFilter[j];
660             V += chrVSrc[j][i] * chrFilter[j];
661         }
662         Y1 >>= 19;
663         Y2 >>= 19;
664         U  >>= 19;
665         V  >>= 19;
666         if ((Y1 | Y2 | U | V) & 0x100) {
667             Y1 = av_clip_uint8(Y1);
668             Y2 = av_clip_uint8(Y2);
669             U  = av_clip_uint8(U);
670             V  = av_clip_uint8(V);
671         }
672         output_pixels(4*i, Y1, U, Y2, V);
673     }
674 }
675
676 static av_always_inline void
677 yuv2422_2_c_template(SwsContext *c, const int16_t *buf[2],
678                      const int16_t *ubuf[2], const int16_t *vbuf[2],
679                      const int16_t *abuf[2], uint8_t *dest, int dstW,
680                      int yalpha, int uvalpha, int y,
681                      enum PixelFormat target)
682 {
683     const int16_t *buf0  = buf[0],  *buf1  = buf[1],
684                   *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
685                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
686     int  yalpha1 = 4095 - yalpha;
687     int uvalpha1 = 4095 - uvalpha;
688     int i;
689
690     for (i = 0; i < (dstW >> 1); i++) {
691         int Y1 = (buf0[i * 2]     * yalpha1  + buf1[i * 2]     * yalpha)  >> 19;
692         int Y2 = (buf0[i * 2 + 1] * yalpha1  + buf1[i * 2 + 1] * yalpha)  >> 19;
693         int U  = (ubuf0[i]        * uvalpha1 + ubuf1[i]        * uvalpha) >> 19;
694         int V  = (vbuf0[i]        * uvalpha1 + vbuf1[i]        * uvalpha) >> 19;
695
696         output_pixels(i * 4, Y1, U, Y2, V);
697     }
698 }
699
700 static av_always_inline void
701 yuv2422_1_c_template(SwsContext *c, const int16_t *buf0,
702                      const int16_t *ubuf[2], const int16_t *vbuf[2],
703                      const int16_t *abuf0, uint8_t *dest, int dstW,
704                      int uvalpha, int y, enum PixelFormat target)
705 {
706     const int16_t *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
707                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
708     int i;
709
710     if (uvalpha < 2048) {
711         for (i = 0; i < (dstW >> 1); i++) {
712             int Y1 = buf0[i * 2]     >> 7;
713             int Y2 = buf0[i * 2 + 1] >> 7;
714             int U  = ubuf1[i]        >> 7;
715             int V  = vbuf1[i]        >> 7;
716
717             output_pixels(i * 4, Y1, U, Y2, V);
718         }
719     } else {
720         for (i = 0; i < (dstW >> 1); i++) {
721             int Y1 =  buf0[i * 2]          >> 7;
722             int Y2 =  buf0[i * 2 + 1]      >> 7;
723             int U  = (ubuf0[i] + ubuf1[i]) >> 8;
724             int V  = (vbuf0[i] + vbuf1[i]) >> 8;
725
726             output_pixels(i * 4, Y1, U, Y2, V);
727         }
728     }
729 }
730
731 #undef output_pixels
732
733 YUV2PACKEDWRAPPER(yuv2, 422, yuyv422, PIX_FMT_YUYV422)
734 YUV2PACKEDWRAPPER(yuv2, 422, uyvy422, PIX_FMT_UYVY422)
735
736 #define R_B ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? R : B)
737 #define B_R ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? B : R)
738 #define output_pixel(pos, val) \
739     if (isBE(target)) { \
740         AV_WB16(pos, val); \
741     } else { \
742         AV_WL16(pos, val); \
743     }
744
745 static av_always_inline void
746 yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter,
747                        const int32_t **lumSrc, int lumFilterSize,
748                        const int16_t *chrFilter, const int32_t **chrUSrc,
749                        const int32_t **chrVSrc, int chrFilterSize,
750                        const int32_t **alpSrc, uint16_t *dest, int dstW,
751                        int y, enum PixelFormat target)
752 {
753     int i;
754
755     for (i = 0; i < (dstW >> 1); i++) {
756         int j;
757         int Y1 = -0x40000000;
758         int Y2 = -0x40000000;
759         int U  = -128 << 23; // 19
760         int V  = -128 << 23;
761         int R, G, B;
762
763         for (j = 0; j < lumFilterSize; j++) {
764             Y1 += lumSrc[j][i * 2]     * lumFilter[j];
765             Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
766         }
767         for (j = 0; j < chrFilterSize; j++) {
768             U += chrUSrc[j][i] * chrFilter[j];
769             V += chrVSrc[j][i] * chrFilter[j];
770         }
771
772         // 8bit: 12+15=27; 16-bit: 12+19=31
773         Y1 >>= 14; // 10
774         Y1 += 0x10000;
775         Y2 >>= 14;
776         Y2 += 0x10000;
777         U  >>= 14;
778         V  >>= 14;
779
780         // 8bit: 27 -> 17bit, 16bit: 31 - 14 = 17bit
781         Y1 -= c->yuv2rgb_y_offset;
782         Y2 -= c->yuv2rgb_y_offset;
783         Y1 *= c->yuv2rgb_y_coeff;
784         Y2 *= c->yuv2rgb_y_coeff;
785         Y1 += 1 << 13; // 21
786         Y2 += 1 << 13;
787         // 8bit: 17 + 13bit = 30bit, 16bit: 17 + 13bit = 30bit
788
789         R = V * c->yuv2rgb_v2r_coeff;
790         G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
791         B =                            U * c->yuv2rgb_u2b_coeff;
792
793         // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit
794         output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
795         output_pixel(&dest[1], av_clip_uintp2(  G + Y1, 30) >> 14);
796         output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
797         output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
798         output_pixel(&dest[4], av_clip_uintp2(  G + Y2, 30) >> 14);
799         output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
800         dest += 6;
801     }
802 }
803
804 static av_always_inline void
805 yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2],
806                        const int32_t *ubuf[2], const int32_t *vbuf[2],
807                        const int32_t *abuf[2], uint16_t *dest, int dstW,
808                        int yalpha, int uvalpha, int y,
809                        enum PixelFormat target)
810 {
811     const int32_t *buf0  = buf[0],  *buf1  = buf[1],
812                   *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
813                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
814     int  yalpha1 = 4095 - yalpha;
815     int uvalpha1 = 4095 - uvalpha;
816     int i;
817
818     for (i = 0; i < (dstW >> 1); i++) {
819         int Y1 = (buf0[i * 2]     * yalpha1  + buf1[i * 2]     * yalpha) >> 14;
820         int Y2 = (buf0[i * 2 + 1] * yalpha1  + buf1[i * 2 + 1] * yalpha) >> 14;
821         int U  = (ubuf0[i]        * uvalpha1 + ubuf1[i]        * uvalpha + (-128 << 23)) >> 14;
822         int V  = (vbuf0[i]        * uvalpha1 + vbuf1[i]        * uvalpha + (-128 << 23)) >> 14;
823         int R, G, B;
824
825         Y1 -= c->yuv2rgb_y_offset;
826         Y2 -= c->yuv2rgb_y_offset;
827         Y1 *= c->yuv2rgb_y_coeff;
828         Y2 *= c->yuv2rgb_y_coeff;
829         Y1 += 1 << 13;
830         Y2 += 1 << 13;
831
832         R = V * c->yuv2rgb_v2r_coeff;
833         G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
834         B =                            U * c->yuv2rgb_u2b_coeff;
835
836         output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
837         output_pixel(&dest[1], av_clip_uintp2(  G + Y1, 30) >> 14);
838         output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
839         output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
840         output_pixel(&dest[4], av_clip_uintp2(  G + Y2, 30) >> 14);
841         output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
842         dest += 6;
843     }
844 }
845
846 static av_always_inline void
847 yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0,
848                        const int32_t *ubuf[2], const int32_t *vbuf[2],
849                        const int32_t *abuf0, uint16_t *dest, int dstW,
850                        int uvalpha, int y, enum PixelFormat target)
851 {
852     const int32_t *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
853                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
854     int i;
855
856     if (uvalpha < 2048) {
857         for (i = 0; i < (dstW >> 1); i++) {
858             int Y1 = (buf0[i * 2]    ) >> 2;
859             int Y2 = (buf0[i * 2 + 1]) >> 2;
860             int U  = (ubuf0[i] + (-128 << 11)) >> 2;
861             int V  = (vbuf0[i] + (-128 << 11)) >> 2;
862             int R, G, B;
863
864             Y1 -= c->yuv2rgb_y_offset;
865             Y2 -= c->yuv2rgb_y_offset;
866             Y1 *= c->yuv2rgb_y_coeff;
867             Y2 *= c->yuv2rgb_y_coeff;
868             Y1 += 1 << 13;
869             Y2 += 1 << 13;
870
871             R = V * c->yuv2rgb_v2r_coeff;
872             G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
873             B =                            U * c->yuv2rgb_u2b_coeff;
874
875             output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
876             output_pixel(&dest[1], av_clip_uintp2(  G + Y1, 30) >> 14);
877             output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
878             output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
879             output_pixel(&dest[4], av_clip_uintp2(  G + Y2, 30) >> 14);
880             output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
881             dest += 6;
882         }
883     } else {
884         for (i = 0; i < (dstW >> 1); i++) {
885             int Y1 = (buf0[i * 2]    ) >> 2;
886             int Y2 = (buf0[i * 2 + 1]) >> 2;
887             int U  = (ubuf0[i] + ubuf1[i] + (-128 << 11)) >> 3;
888             int V  = (vbuf0[i] + vbuf1[i] + (-128 << 11)) >> 3;
889             int R, G, B;
890
891             Y1 -= c->yuv2rgb_y_offset;
892             Y2 -= c->yuv2rgb_y_offset;
893             Y1 *= c->yuv2rgb_y_coeff;
894             Y2 *= c->yuv2rgb_y_coeff;
895             Y1 += 1 << 13;
896             Y2 += 1 << 13;
897
898             R = V * c->yuv2rgb_v2r_coeff;
899             G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
900             B =                            U * c->yuv2rgb_u2b_coeff;
901
902             output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
903             output_pixel(&dest[1], av_clip_uintp2(  G + Y1, 30) >> 14);
904             output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
905             output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
906             output_pixel(&dest[4], av_clip_uintp2(  G + Y2, 30) >> 14);
907             output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
908             dest += 6;
909         }
910     }
911 }
912
913 #undef output_pixel
914 #undef r_b
915 #undef b_r
916
917 YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48be, PIX_FMT_RGB48BE)
918 YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48le, PIX_FMT_RGB48LE)
919 YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48be, PIX_FMT_BGR48BE)
920 YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48le, PIX_FMT_BGR48LE)
921
922 static av_always_inline void
923 yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2,
924               int U, int V, int A1, int A2,
925               const void *_r, const void *_g, const void *_b, int y,
926               enum PixelFormat target, int hasAlpha)
927 {
928     if (target == PIX_FMT_ARGB || target == PIX_FMT_RGBA ||
929         target == PIX_FMT_ABGR || target == PIX_FMT_BGRA) {
930         uint32_t *dest = (uint32_t *) _dest;
931         const uint32_t *r = (const uint32_t *) _r;
932         const uint32_t *g = (const uint32_t *) _g;
933         const uint32_t *b = (const uint32_t *) _b;
934
935 #if CONFIG_SMALL
936         int sh = hasAlpha ? ((target == PIX_FMT_RGB32_1 || target == PIX_FMT_BGR32_1) ? 0 : 24) : 0;
937
938         dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1] + (hasAlpha ? A1 << sh : 0);
939         dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2] + (hasAlpha ? A2 << sh : 0);
940 #else
941         if (hasAlpha) {
942             int sh = (target == PIX_FMT_RGB32_1 || target == PIX_FMT_BGR32_1) ? 0 : 24;
943
944             dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1] + (A1 << sh);
945             dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2] + (A2 << sh);
946         } else {
947             dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1];
948             dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2];
949         }
950 #endif
951     } else if (target == PIX_FMT_RGB24 || target == PIX_FMT_BGR24) {
952         uint8_t *dest = (uint8_t *) _dest;
953         const uint8_t *r = (const uint8_t *) _r;
954         const uint8_t *g = (const uint8_t *) _g;
955         const uint8_t *b = (const uint8_t *) _b;
956
957 #define r_b ((target == PIX_FMT_RGB24) ? r : b)
958 #define b_r ((target == PIX_FMT_RGB24) ? b : r)
959         dest[i * 6 + 0] = r_b[Y1];
960         dest[i * 6 + 1] =   g[Y1];
961         dest[i * 6 + 2] = b_r[Y1];
962         dest[i * 6 + 3] = r_b[Y2];
963         dest[i * 6 + 4] =   g[Y2];
964         dest[i * 6 + 5] = b_r[Y2];
965 #undef r_b
966 #undef b_r
967     } else if (target == PIX_FMT_RGB565 || target == PIX_FMT_BGR565 ||
968                target == PIX_FMT_RGB555 || target == PIX_FMT_BGR555 ||
969                target == PIX_FMT_RGB444 || target == PIX_FMT_BGR444) {
970         uint16_t *dest = (uint16_t *) _dest;
971         const uint16_t *r = (const uint16_t *) _r;
972         const uint16_t *g = (const uint16_t *) _g;
973         const uint16_t *b = (const uint16_t *) _b;
974         int dr1, dg1, db1, dr2, dg2, db2;
975
976         if (target == PIX_FMT_RGB565 || target == PIX_FMT_BGR565) {
977             dr1 = dither_2x2_8[ y & 1     ][0];
978             dg1 = dither_2x2_4[ y & 1     ][0];
979             db1 = dither_2x2_8[(y & 1) ^ 1][0];
980             dr2 = dither_2x2_8[ y & 1     ][1];
981             dg2 = dither_2x2_4[ y & 1     ][1];
982             db2 = dither_2x2_8[(y & 1) ^ 1][1];
983         } else if (target == PIX_FMT_RGB555 || target == PIX_FMT_BGR555) {
984             dr1 = dither_2x2_8[ y & 1     ][0];
985             dg1 = dither_2x2_8[ y & 1     ][1];
986             db1 = dither_2x2_8[(y & 1) ^ 1][0];
987             dr2 = dither_2x2_8[ y & 1     ][1];
988             dg2 = dither_2x2_8[ y & 1     ][0];
989             db2 = dither_2x2_8[(y & 1) ^ 1][1];
990         } else {
991             dr1 = dither_4x4_16[ y & 3     ][0];
992             dg1 = dither_4x4_16[ y & 3     ][1];
993             db1 = dither_4x4_16[(y & 3) ^ 3][0];
994             dr2 = dither_4x4_16[ y & 3     ][1];
995             dg2 = dither_4x4_16[ y & 3     ][0];
996             db2 = dither_4x4_16[(y & 3) ^ 3][1];
997         }
998
999         dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
1000         dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
1001     } else /* 8/4-bit */ {
1002         uint8_t *dest = (uint8_t *) _dest;
1003         const uint8_t *r = (const uint8_t *) _r;
1004         const uint8_t *g = (const uint8_t *) _g;
1005         const uint8_t *b = (const uint8_t *) _b;
1006         int dr1, dg1, db1, dr2, dg2, db2;
1007
1008         if (target == PIX_FMT_RGB8 || target == PIX_FMT_BGR8) {
1009             const uint8_t * const d64 = dither_8x8_73[y & 7];
1010             const uint8_t * const d32 = dither_8x8_32[y & 7];
1011             dr1 = dg1 = d32[(i * 2 + 0) & 7];
1012             db1 =       d64[(i * 2 + 0) & 7];
1013             dr2 = dg2 = d32[(i * 2 + 1) & 7];
1014             db2 =       d64[(i * 2 + 1) & 7];
1015         } else {
1016             const uint8_t * const d64  = dither_8x8_73 [y & 7];
1017             const uint8_t * const d128 = dither_8x8_220[y & 7];
1018             dr1 = db1 = d128[(i * 2 + 0) & 7];
1019             dg1 =        d64[(i * 2 + 0) & 7];
1020             dr2 = db2 = d128[(i * 2 + 1) & 7];
1021             dg2 =        d64[(i * 2 + 1) & 7];
1022         }
1023
1024         if (target == PIX_FMT_RGB4 || target == PIX_FMT_BGR4) {
1025             dest[i] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1] +
1026                     ((r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]) << 4);
1027         } else {
1028             dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
1029             dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
1030         }
1031     }
1032 }
1033
1034 static av_always_inline void
1035 yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter,
1036                      const int16_t **lumSrc, int lumFilterSize,
1037                      const int16_t *chrFilter, const int16_t **chrUSrc,
1038                      const int16_t **chrVSrc, int chrFilterSize,
1039                      const int16_t **alpSrc, uint8_t *dest, int dstW,
1040                      int y, enum PixelFormat target, int hasAlpha)
1041 {
1042     int i;
1043
1044     for (i = 0; i < (dstW >> 1); i++) {
1045         int j;
1046         int Y1 = 1 << 18;
1047         int Y2 = 1 << 18;
1048         int U  = 1 << 18;
1049         int V  = 1 << 18;
1050         int av_unused A1, A2;
1051         const void *r, *g, *b;
1052
1053         for (j = 0; j < lumFilterSize; j++) {
1054             Y1 += lumSrc[j][i * 2]     * lumFilter[j];
1055             Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
1056         }
1057         for (j = 0; j < chrFilterSize; j++) {
1058             U += chrUSrc[j][i] * chrFilter[j];
1059             V += chrVSrc[j][i] * chrFilter[j];
1060         }
1061         Y1 >>= 19;
1062         Y2 >>= 19;
1063         U  >>= 19;
1064         V  >>= 19;
1065         if ((Y1 | Y2 | U | V) & 0x100) {
1066             Y1 = av_clip_uint8(Y1);
1067             Y2 = av_clip_uint8(Y2);
1068             U  = av_clip_uint8(U);
1069             V  = av_clip_uint8(V);
1070         }
1071         if (hasAlpha) {
1072             A1 = 1 << 18;
1073             A2 = 1 << 18;
1074             for (j = 0; j < lumFilterSize; j++) {
1075                 A1 += alpSrc[j][i * 2    ] * lumFilter[j];
1076                 A2 += alpSrc[j][i * 2 + 1] * lumFilter[j];
1077             }
1078             A1 >>= 19;
1079             A2 >>= 19;
1080             if ((A1 | A2) & 0x100) {
1081                 A1 = av_clip_uint8(A1);
1082                 A2 = av_clip_uint8(A2);
1083             }
1084         }
1085
1086         /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/
1087         r =  c->table_rV[V];
1088         g = (c->table_gU[U] + c->table_gV[V]);
1089         b =  c->table_bU[U];
1090
1091         yuv2rgb_write(dest, i, Y1, Y2, U, V, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
1092                       r, g, b, y, target, hasAlpha);
1093     }
1094 }
1095
1096 static av_always_inline void
1097 yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2],
1098                      const int16_t *ubuf[2], const int16_t *vbuf[2],
1099                      const int16_t *abuf[2], uint8_t *dest, int dstW,
1100                      int yalpha, int uvalpha, int y,
1101                      enum PixelFormat target, int hasAlpha)
1102 {
1103     const int16_t *buf0  = buf[0],  *buf1  = buf[1],
1104                   *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
1105                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1],
1106                   *abuf0 = hasAlpha ? abuf[0] : NULL,
1107                   *abuf1 = hasAlpha ? abuf[1] : NULL;
1108     int  yalpha1 = 4095 - yalpha;
1109     int uvalpha1 = 4095 - uvalpha;
1110     int i;
1111
1112     for (i = 0; i < (dstW >> 1); i++) {
1113         int Y1 = (buf0[i * 2]     * yalpha1  + buf1[i * 2]     * yalpha)  >> 19;
1114         int Y2 = (buf0[i * 2 + 1] * yalpha1  + buf1[i * 2 + 1] * yalpha)  >> 19;
1115         int U  = (ubuf0[i]        * uvalpha1 + ubuf1[i]        * uvalpha) >> 19;
1116         int V  = (vbuf0[i]        * uvalpha1 + vbuf1[i]        * uvalpha) >> 19;
1117         int A1, A2;
1118         const void *r =  c->table_rV[V],
1119                    *g = (c->table_gU[U] + c->table_gV[V]),
1120                    *b =  c->table_bU[U];
1121
1122         if (hasAlpha) {
1123             A1 = (abuf0[i * 2    ] * yalpha1 + abuf1[i * 2    ] * yalpha) >> 19;
1124             A2 = (abuf0[i * 2 + 1] * yalpha1 + abuf1[i * 2 + 1] * yalpha) >> 19;
1125         }
1126
1127         yuv2rgb_write(dest, i, Y1, Y2, U, V, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
1128                       r, g, b, y, target, hasAlpha);
1129     }
1130 }
1131
1132 static av_always_inline void
1133 yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0,
1134                      const int16_t *ubuf[2], const int16_t *vbuf[2],
1135                      const int16_t *abuf0, uint8_t *dest, int dstW,
1136                      int uvalpha, int y, enum PixelFormat target,
1137                      int hasAlpha)
1138 {
1139     const int16_t *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
1140                   *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
1141     int i;
1142
1143     if (uvalpha < 2048) {
1144         for (i = 0; i < (dstW >> 1); i++) {
1145             int Y1 = buf0[i * 2]     >> 7;
1146             int Y2 = buf0[i * 2 + 1] >> 7;
1147             int U  = ubuf1[i]        >> 7;
1148             int V  = vbuf1[i]        >> 7;
1149             int A1, A2;
1150             const void *r =  c->table_rV[V],
1151                        *g = (c->table_gU[U] + c->table_gV[V]),
1152                        *b =  c->table_bU[U];
1153
1154             if (hasAlpha) {
1155                 A1 = abuf0[i * 2    ] >> 7;
1156                 A2 = abuf0[i * 2 + 1] >> 7;
1157             }
1158
1159             yuv2rgb_write(dest, i, Y1, Y2, U, V, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
1160                           r, g, b, y, target, hasAlpha);
1161         }
1162     } else {
1163         for (i = 0; i < (dstW >> 1); i++) {
1164             int Y1 =  buf0[i * 2]          >> 7;
1165             int Y2 =  buf0[i * 2 + 1]      >> 7;
1166             int U  = (ubuf0[i] + ubuf1[i]) >> 8;
1167             int V  = (vbuf0[i] + vbuf1[i]) >> 8;
1168             int A1, A2;
1169             const void *r =  c->table_rV[V],
1170                        *g = (c->table_gU[U] + c->table_gV[V]),
1171                        *b =  c->table_bU[U];
1172
1173             if (hasAlpha) {
1174                 A1 = abuf0[i * 2    ] >> 7;
1175                 A2 = abuf0[i * 2 + 1] >> 7;
1176             }
1177
1178             yuv2rgb_write(dest, i, Y1, Y2, U, V, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
1179                           r, g, b, y, target, hasAlpha);
1180         }
1181     }
1182 }
1183
1184 #define YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \
1185 static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
1186                                 const int16_t **lumSrc, int lumFilterSize, \
1187                                 const int16_t *chrFilter, const int16_t **chrUSrc, \
1188                                 const int16_t **chrVSrc, int chrFilterSize, \
1189                                 const int16_t **alpSrc, uint8_t *dest, int dstW, \
1190                                 int y) \
1191 { \
1192     name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
1193                                   chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
1194                                   alpSrc, dest, dstW, y, fmt, hasAlpha); \
1195 }
1196 #define YUV2RGBWRAPPER(name, base, ext, fmt, hasAlpha) \
1197 YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \
1198 static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
1199                                 const int16_t *ubuf[2], const int16_t *vbuf[2], \
1200                                 const int16_t *abuf[2], uint8_t *dest, int dstW, \
1201                                 int yalpha, int uvalpha, int y) \
1202 { \
1203     name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
1204                                   dest, dstW, yalpha, uvalpha, y, fmt, hasAlpha); \
1205 } \
1206  \
1207 static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
1208                                 const int16_t *ubuf[2], const int16_t *vbuf[2], \
1209                                 const int16_t *abuf0, uint8_t *dest, int dstW, \
1210                                 int uvalpha, int y) \
1211 { \
1212     name ## base ## _1_c_template(c, buf0, ubuf, vbuf, abuf0, dest, \
1213                                   dstW, uvalpha, y, fmt, hasAlpha); \
1214 }
1215
1216 #if CONFIG_SMALL
1217 YUV2RGBWRAPPER(yuv2rgb,,  32_1,  PIX_FMT_RGB32_1,   CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1218 YUV2RGBWRAPPER(yuv2rgb,,  32,    PIX_FMT_RGB32,     CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1219 #else
1220 #if CONFIG_SWSCALE_ALPHA
1221 YUV2RGBWRAPPER(yuv2rgb,, a32_1,  PIX_FMT_RGB32_1,   1)
1222 YUV2RGBWRAPPER(yuv2rgb,, a32,    PIX_FMT_RGB32,     1)
1223 #endif
1224 YUV2RGBWRAPPER(yuv2rgb,, x32_1,  PIX_FMT_RGB32_1,   0)
1225 YUV2RGBWRAPPER(yuv2rgb,, x32,    PIX_FMT_RGB32,     0)
1226 #endif
1227 YUV2RGBWRAPPER(yuv2, rgb, rgb24, PIX_FMT_RGB24,   0)
1228 YUV2RGBWRAPPER(yuv2, rgb, bgr24, PIX_FMT_BGR24,   0)
1229 YUV2RGBWRAPPER(yuv2rgb,,  16,    PIX_FMT_RGB565,    0)
1230 YUV2RGBWRAPPER(yuv2rgb,,  15,    PIX_FMT_RGB555,    0)
1231 YUV2RGBWRAPPER(yuv2rgb,,  12,    PIX_FMT_RGB444,    0)
1232 YUV2RGBWRAPPER(yuv2rgb,,   8,    PIX_FMT_RGB8,      0)
1233 YUV2RGBWRAPPER(yuv2rgb,,   4,    PIX_FMT_RGB4,      0)
1234 YUV2RGBWRAPPER(yuv2rgb,,   4b,   PIX_FMT_RGB4_BYTE, 0)
1235
1236 static av_always_inline void
1237 yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter,
1238                           const int16_t **lumSrc, int lumFilterSize,
1239                           const int16_t *chrFilter, const int16_t **chrUSrc,
1240                           const int16_t **chrVSrc, int chrFilterSize,
1241                           const int16_t **alpSrc, uint8_t *dest,
1242                           int dstW, int y, enum PixelFormat target, int hasAlpha)
1243 {
1244     int i;
1245     int step = (target == PIX_FMT_RGB24 || target == PIX_FMT_BGR24) ? 3 : 4;
1246
1247     for (i = 0; i < dstW; i++) {
1248         int j;
1249         int Y = 0;
1250         int U = -128 << 19;
1251         int V = -128 << 19;
1252         int av_unused A;
1253         int R, G, B;
1254
1255         for (j = 0; j < lumFilterSize; j++) {
1256             Y += lumSrc[j][i] * lumFilter[j];
1257         }
1258         for (j = 0; j < chrFilterSize; j++) {
1259             U += chrUSrc[j][i] * chrFilter[j];
1260             V += chrVSrc[j][i] * chrFilter[j];
1261         }
1262         Y >>= 10;
1263         U >>= 10;
1264         V >>= 10;
1265         if (hasAlpha) {
1266             A = 1 << 21;
1267             for (j = 0; j < lumFilterSize; j++) {
1268                 A += alpSrc[j][i] * lumFilter[j];
1269             }
1270             A >>= 19;
1271             if (A & 0x100)
1272                 A = av_clip_uint8(A);
1273         }
1274         Y -= c->yuv2rgb_y_offset;
1275         Y *= c->yuv2rgb_y_coeff;
1276         Y += 1 << 21;
1277         R = Y + V*c->yuv2rgb_v2r_coeff;
1278         G = Y + V*c->yuv2rgb_v2g_coeff + U*c->yuv2rgb_u2g_coeff;
1279         B = Y +                          U*c->yuv2rgb_u2b_coeff;
1280         if ((R | G | B) & 0xC0000000) {
1281             R = av_clip_uintp2(R, 30);
1282             G = av_clip_uintp2(G, 30);
1283             B = av_clip_uintp2(B, 30);
1284         }
1285
1286         switch(target) {
1287         case PIX_FMT_ARGB:
1288             dest[0] = hasAlpha ? A : 255;
1289             dest[1] = R >> 22;
1290             dest[2] = G >> 22;
1291             dest[3] = B >> 22;
1292             break;
1293         case PIX_FMT_RGB24:
1294             dest[0] = R >> 22;
1295             dest[1] = G >> 22;
1296             dest[2] = B >> 22;
1297             break;
1298         case PIX_FMT_RGBA:
1299             dest[0] = R >> 22;
1300             dest[1] = G >> 22;
1301             dest[2] = B >> 22;
1302             dest[3] = hasAlpha ? A : 255;
1303             break;
1304         case PIX_FMT_ABGR:
1305             dest[0] = hasAlpha ? A : 255;
1306             dest[1] = B >> 22;
1307             dest[2] = G >> 22;
1308             dest[3] = R >> 22;
1309             dest += 4;
1310             break;
1311         case PIX_FMT_BGR24:
1312             dest[0] = B >> 22;
1313             dest[1] = G >> 22;
1314             dest[2] = R >> 22;
1315             break;
1316         case PIX_FMT_BGRA:
1317             dest[0] = B >> 22;
1318             dest[1] = G >> 22;
1319             dest[2] = R >> 22;
1320             dest[3] = hasAlpha ? A : 255;
1321             break;
1322         }
1323         dest += step;
1324     }
1325 }
1326
1327 #if CONFIG_SMALL
1328 YUV2RGBWRAPPERX(yuv2, rgb_full, bgra32_full, PIX_FMT_BGRA,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1329 YUV2RGBWRAPPERX(yuv2, rgb_full, abgr32_full, PIX_FMT_ABGR,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1330 YUV2RGBWRAPPERX(yuv2, rgb_full, rgba32_full, PIX_FMT_RGBA,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1331 YUV2RGBWRAPPERX(yuv2, rgb_full, argb32_full, PIX_FMT_ARGB,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
1332 #else
1333 #if CONFIG_SWSCALE_ALPHA
1334 YUV2RGBWRAPPERX(yuv2, rgb_full, bgra32_full, PIX_FMT_BGRA,  1)
1335 YUV2RGBWRAPPERX(yuv2, rgb_full, abgr32_full, PIX_FMT_ABGR,  1)
1336 YUV2RGBWRAPPERX(yuv2, rgb_full, rgba32_full, PIX_FMT_RGBA,  1)
1337 YUV2RGBWRAPPERX(yuv2, rgb_full, argb32_full, PIX_FMT_ARGB,  1)
1338 #endif
1339 YUV2RGBWRAPPERX(yuv2, rgb_full, bgrx32_full, PIX_FMT_BGRA,  0)
1340 YUV2RGBWRAPPERX(yuv2, rgb_full, xbgr32_full, PIX_FMT_ABGR,  0)
1341 YUV2RGBWRAPPERX(yuv2, rgb_full, rgbx32_full, PIX_FMT_RGBA,  0)
1342 YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, PIX_FMT_ARGB,  0)
1343 #endif
1344 YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full,  PIX_FMT_BGR24, 0)
1345 YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full,  PIX_FMT_RGB24, 0)
1346
1347 static av_always_inline void fillPlane(uint8_t* plane, int stride,
1348                                        int width, int height,
1349                                        int y, uint8_t val)
1350 {
1351     int i;
1352     uint8_t *ptr = plane + stride*y;
1353     for (i=0; i<height; i++) {
1354         memset(ptr, val, width);
1355         ptr += stride;
1356     }
1357 }
1358
1359 #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
1360
1361 #define r ((origin == PIX_FMT_BGR48BE || origin == PIX_FMT_BGR48LE) ? b_r : r_b)
1362 #define b ((origin == PIX_FMT_BGR48BE || origin == PIX_FMT_BGR48LE) ? r_b : b_r)
1363
1364 static av_always_inline void
1365 rgb48ToY_c_template(uint16_t *dst, const uint16_t *src, int width,
1366                     enum PixelFormat origin)
1367 {
1368     int i;
1369     for (i = 0; i < width; i++) {
1370         unsigned int r_b = input_pixel(&src[i*3+0]);
1371         unsigned int   g = input_pixel(&src[i*3+1]);
1372         unsigned int b_r = input_pixel(&src[i*3+2]);
1373
1374         dst[i] = (RY*r + GY*g + BY*b + (0x2001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
1375     }
1376 }
1377
1378 static av_always_inline void
1379 rgb48ToUV_c_template(uint16_t *dstU, uint16_t *dstV,
1380                     const uint16_t *src1, const uint16_t *src2,
1381                     int width, enum PixelFormat origin)
1382 {
1383     int i;
1384     assert(src1==src2);
1385     for (i = 0; i < width; i++) {
1386         int r_b = input_pixel(&src1[i*3+0]);
1387         int   g = input_pixel(&src1[i*3+1]);
1388         int b_r = input_pixel(&src1[i*3+2]);
1389
1390         dstU[i] = (RU*r + GU*g + BU*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
1391         dstV[i] = (RV*r + GV*g + BV*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
1392     }
1393 }
1394
1395 static av_always_inline void
1396 rgb48ToUV_half_c_template(uint16_t *dstU, uint16_t *dstV,
1397                           const uint16_t *src1, const uint16_t *src2,
1398                           int width, enum PixelFormat origin)
1399 {
1400     int i;
1401     assert(src1==src2);
1402     for (i = 0; i < width; i++) {
1403         int r_b = (input_pixel(&src1[6 * i + 0]) + input_pixel(&src1[6 * i + 3]) + 1) >> 1;
1404         int   g = (input_pixel(&src1[6 * i + 1]) + input_pixel(&src1[6 * i + 4]) + 1) >> 1;
1405         int b_r = (input_pixel(&src1[6 * i + 2]) + input_pixel(&src1[6 * i + 5]) + 1) >> 1;
1406
1407         dstU[i]= (RU*r + GU*g + BU*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
1408         dstV[i]= (RV*r + GV*g + BV*b + (0x10001<<(RGB2YUV_SHIFT-1))) >> RGB2YUV_SHIFT;
1409     }
1410 }
1411
1412 #undef r
1413 #undef b
1414 #undef input_pixel
1415
1416 #define rgb48funcs(pattern, BE_LE, origin) \
1417 static void pattern ## 48 ## BE_LE ## ToY_c(uint8_t *_dst, const uint8_t *_src, \
1418                                     int width, uint32_t *unused) \
1419 { \
1420     const uint16_t *src = (const uint16_t *) _src; \
1421     uint16_t *dst = (uint16_t *) _dst; \
1422     rgb48ToY_c_template(dst, src, width, origin); \
1423 } \
1424  \
1425 static void pattern ## 48 ## BE_LE ## ToUV_c(uint8_t *_dstU, uint8_t *_dstV, \
1426                                     const uint8_t *_src1, const uint8_t *_src2, \
1427                                     int width, uint32_t *unused) \
1428 { \
1429     const uint16_t *src1 = (const uint16_t *) _src1, \
1430                    *src2 = (const uint16_t *) _src2; \
1431     uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV; \
1432     rgb48ToUV_c_template(dstU, dstV, src1, src2, width, origin); \
1433 } \
1434  \
1435 static void pattern ## 48 ## BE_LE ## ToUV_half_c(uint8_t *_dstU, uint8_t *_dstV, \
1436                                     const uint8_t *_src1, const uint8_t *_src2, \
1437                                     int width, uint32_t *unused) \
1438 { \
1439     const uint16_t *src1 = (const uint16_t *) _src1, \
1440                    *src2 = (const uint16_t *) _src2; \
1441     uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV; \
1442     rgb48ToUV_half_c_template(dstU, dstV, src1, src2, width, origin); \
1443 }
1444
1445 rgb48funcs(rgb, LE, PIX_FMT_RGB48LE)
1446 rgb48funcs(rgb, BE, PIX_FMT_RGB48BE)
1447 rgb48funcs(bgr, LE, PIX_FMT_BGR48LE)
1448 rgb48funcs(bgr, BE, PIX_FMT_BGR48BE)
1449
1450 #define input_pixel(i) ((origin == PIX_FMT_RGBA || origin == PIX_FMT_BGRA || \
1451                          origin == PIX_FMT_ARGB || origin == PIX_FMT_ABGR) ? AV_RN32A(&src[(i)*4]) : \
1452                         (isBE(origin) ? AV_RB16(&src[(i)*2]) : AV_RL16(&src[(i)*2])))
1453
1454 static av_always_inline void
1455 rgb16_32ToY_c_template(uint8_t *dst, const uint8_t *src,
1456                        int width, enum PixelFormat origin,
1457                        int shr,   int shg,   int shb, int shp,
1458                        int maskr, int maskg, int maskb,
1459                        int rsh,   int gsh,   int bsh, int S)
1460 {
1461     const int ry = RY << rsh, gy = GY << gsh, by = BY << bsh;
1462     const unsigned rnd = 33u << (S - 1);
1463     int i;
1464
1465     for (i = 0; i < width; i++) {
1466         int px = input_pixel(i) >> shp;
1467         int b = (px & maskb) >> shb;
1468         int g = (px & maskg) >> shg;
1469         int r = (px & maskr) >> shr;
1470
1471         dst[i] = (ry * r + gy * g + by * b + rnd) >> S;
1472     }
1473 }
1474
1475 static av_always_inline void
1476 rgb16_32ToUV_c_template(uint8_t *dstU, uint8_t *dstV,
1477                         const uint8_t *src, int width,
1478                         enum PixelFormat origin,
1479                         int shr,   int shg,   int shb, int shp,
1480                         int maskr, int maskg, int maskb,
1481                         int rsh,   int gsh,   int bsh, int S)
1482 {
1483     const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
1484               rv = RV << rsh, gv = GV << gsh, bv = BV << bsh;
1485     const unsigned rnd = 257u << (S - 1);
1486     int i;
1487
1488     for (i = 0; i < width; i++) {
1489         int px = input_pixel(i) >> shp;
1490         int b = (px & maskb) >> shb;
1491         int g = (px & maskg) >> shg;
1492         int r = (px & maskr) >> shr;
1493
1494         dstU[i] = (ru * r + gu * g + bu * b + rnd) >> S;
1495         dstV[i] = (rv * r + gv * g + bv * b + rnd) >> S;
1496     }
1497 }
1498
1499 static av_always_inline void
1500 rgb16_32ToUV_half_c_template(uint8_t *dstU, uint8_t *dstV,
1501                              const uint8_t *src, int width,
1502                              enum PixelFormat origin,
1503                              int shr,   int shg,   int shb, int shp,
1504                              int maskr, int maskg, int maskb,
1505                              int rsh,   int gsh,   int bsh, int S)
1506 {
1507     const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh,
1508               rv = RV << rsh, gv = GV << gsh, bv = BV << bsh,
1509               maskgx = ~(maskr | maskb);
1510     const unsigned rnd = 257u << S;
1511     int i;
1512
1513     maskr |= maskr << 1; maskb |= maskb << 1; maskg |= maskg << 1;
1514     for (i = 0; i < width; i++) {
1515         int px0 = input_pixel(2 * i + 0) >> shp;
1516         int px1 = input_pixel(2 * i + 1) >> shp;
1517         int b, r, g = (px0 & maskgx) + (px1 & maskgx);
1518         int rb = px0 + px1 - g;
1519
1520         b = (rb & maskb) >> shb;
1521         if (shp || origin == PIX_FMT_BGR565LE || origin == PIX_FMT_BGR565BE ||
1522             origin == PIX_FMT_RGB565LE || origin == PIX_FMT_RGB565BE) {
1523             g >>= shg;
1524         } else {
1525             g = (g  & maskg) >> shg;
1526         }
1527         r = (rb & maskr) >> shr;
1528
1529         dstU[i] = (ru * r + gu * g + bu * b + rnd) >> (S + 1);
1530         dstV[i] = (rv * r + gv * g + bv * b + rnd) >> (S + 1);
1531     }
1532 }
1533
1534 #undef input_pixel
1535
1536 #define rgb16_32_wrapper(fmt, name, shr, shg, shb, shp, maskr, \
1537                          maskg, maskb, rsh, gsh, bsh, S) \
1538 static void name ## ToY_c(uint8_t *dst, const uint8_t *src, \
1539                           int width, uint32_t *unused) \
1540 { \
1541     rgb16_32ToY_c_template(dst, src, width, fmt, shr, shg, shb, shp, \
1542                            maskr, maskg, maskb, rsh, gsh, bsh, S); \
1543 } \
1544  \
1545 static void name ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
1546                            const uint8_t *src, const uint8_t *dummy, \
1547                            int width, uint32_t *unused) \
1548 { \
1549     rgb16_32ToUV_c_template(dstU, dstV, src, width, fmt, shr, shg, shb, shp, \
1550                             maskr, maskg, maskb, rsh, gsh, bsh, S); \
1551 } \
1552  \
1553 static void name ## ToUV_half_c(uint8_t *dstU, uint8_t *dstV, \
1554                                 const uint8_t *src, const uint8_t *dummy, \
1555                                 int width, uint32_t *unused) \
1556 { \
1557     rgb16_32ToUV_half_c_template(dstU, dstV, src, width, fmt, shr, shg, shb, shp, \
1558                                  maskr, maskg, maskb, rsh, gsh, bsh, S); \
1559 }
1560
1561 rgb16_32_wrapper(PIX_FMT_BGR32,    bgr32,  16, 0,  0, 0, 0xFF0000, 0xFF00,   0x00FF,  8, 0,  8, RGB2YUV_SHIFT+8)
1562 rgb16_32_wrapper(PIX_FMT_BGR32_1,  bgr321, 16, 0,  0, 8, 0xFF0000, 0xFF00,   0x00FF,  8, 0,  8, RGB2YUV_SHIFT+8)
1563 rgb16_32_wrapper(PIX_FMT_RGB32,    rgb32,   0, 0, 16, 0,   0x00FF, 0xFF00, 0xFF0000,  8, 0,  8, RGB2YUV_SHIFT+8)
1564 rgb16_32_wrapper(PIX_FMT_RGB32_1,  rgb321,  0, 0, 16, 8,   0x00FF, 0xFF00, 0xFF0000,  8, 0,  8, RGB2YUV_SHIFT+8)
1565 rgb16_32_wrapper(PIX_FMT_BGR565LE, bgr16le, 0, 0,  0, 0,   0x001F, 0x07E0,   0xF800, 11, 5,  0, RGB2YUV_SHIFT+8)
1566 rgb16_32_wrapper(PIX_FMT_BGR555LE, bgr15le, 0, 0,  0, 0,   0x001F, 0x03E0,   0x7C00, 10, 5,  0, RGB2YUV_SHIFT+7)
1567 rgb16_32_wrapper(PIX_FMT_RGB565LE, rgb16le, 0, 0,  0, 0,   0xF800, 0x07E0,   0x001F,  0, 5, 11, RGB2YUV_SHIFT+8)
1568 rgb16_32_wrapper(PIX_FMT_RGB555LE, rgb15le, 0, 0,  0, 0,   0x7C00, 0x03E0,   0x001F,  0, 5, 10, RGB2YUV_SHIFT+7)
1569 rgb16_32_wrapper(PIX_FMT_BGR565BE, bgr16be, 0, 0,  0, 0,   0x001F, 0x07E0,   0xF800, 11, 5,  0, RGB2YUV_SHIFT+8)
1570 rgb16_32_wrapper(PIX_FMT_BGR555BE, bgr15be, 0, 0,  0, 0,   0x001F, 0x03E0,   0x7C00, 10, 5,  0, RGB2YUV_SHIFT+7)
1571 rgb16_32_wrapper(PIX_FMT_RGB565BE, rgb16be, 0, 0,  0, 0,   0xF800, 0x07E0,   0x001F,  0, 5, 11, RGB2YUV_SHIFT+8)
1572 rgb16_32_wrapper(PIX_FMT_RGB555BE, rgb15be, 0, 0,  0, 0,   0x7C00, 0x03E0,   0x001F,  0, 5, 10, RGB2YUV_SHIFT+7)
1573
1574 static void abgrToA_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)
1575 {
1576     int i;
1577     for (i=0; i<width; i++) {
1578         dst[i]= src[4*i];
1579     }
1580 }
1581
1582 static void rgbaToA_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)
1583 {
1584     int i;
1585     for (i=0; i<width; i++) {
1586         dst[i]= src[4*i+3];
1587     }
1588 }
1589
1590 static void palToY_c(uint8_t *dst, const uint8_t *src, int width, uint32_t *pal)
1591 {
1592     int i;
1593     for (i=0; i<width; i++) {
1594         int d= src[i];
1595
1596         dst[i]= pal[d] & 0xFF;
1597     }
1598 }
1599
1600 static void palToUV_c(uint8_t *dstU, uint8_t *dstV,
1601                       const uint8_t *src1, const uint8_t *src2,
1602                       int width, uint32_t *pal)
1603 {
1604     int i;
1605     assert(src1 == src2);
1606     for (i=0; i<width; i++) {
1607         int p= pal[src1[i]];
1608
1609         dstU[i]= p>>8;
1610         dstV[i]= p>>16;
1611     }
1612 }
1613
1614 static void monowhite2Y_c(uint8_t *dst, const uint8_t *src,
1615                           int width, uint32_t *unused)
1616 {
1617     int i, j;
1618     for (i=0; i<width/8; i++) {
1619         int d= ~src[i];
1620         for(j=0; j<8; j++)
1621             dst[8*i+j]= ((d>>(7-j))&1)*255;
1622     }
1623 }
1624
1625 static void monoblack2Y_c(uint8_t *dst, const uint8_t *src,
1626                           int width, uint32_t *unused)
1627 {
1628     int i, j;
1629     for (i=0; i<width/8; i++) {
1630         int d= src[i];
1631         for(j=0; j<8; j++)
1632             dst[8*i+j]= ((d>>(7-j))&1)*255;
1633     }
1634 }
1635
1636 //FIXME yuy2* can read up to 7 samples too much
1637
1638 static void yuy2ToY_c(uint8_t *dst, const uint8_t *src, int width,
1639                       uint32_t *unused)
1640 {
1641     int i;
1642     for (i=0; i<width; i++)
1643         dst[i]= src[2*i];
1644 }
1645
1646 static void yuy2ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1647                        const uint8_t *src2, int width, uint32_t *unused)
1648 {
1649     int i;
1650     for (i=0; i<width; i++) {
1651         dstU[i]= src1[4*i + 1];
1652         dstV[i]= src1[4*i + 3];
1653     }
1654     assert(src1 == src2);
1655 }
1656
1657 static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, int width, uint32_t *unused)
1658 {
1659     int i;
1660     const uint16_t *src = (const uint16_t *) _src;
1661     uint16_t *dst = (uint16_t *) _dst;
1662     for (i=0; i<width; i++) {
1663         dst[i] = av_bswap16(src[i]);
1664     }
1665 }
1666
1667 static void bswap16UV_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src1,
1668                         const uint8_t *_src2, int width, uint32_t *unused)
1669 {
1670     int i;
1671     const uint16_t *src1 = (const uint16_t *) _src1,
1672                    *src2 = (const uint16_t *) _src2;
1673     uint16_t *dstU = (uint16_t *) _dstU, *dstV = (uint16_t *) _dstV;
1674     for (i=0; i<width; i++) {
1675         dstU[i] = av_bswap16(src1[i]);
1676         dstV[i] = av_bswap16(src2[i]);
1677     }
1678 }
1679
1680 /* This is almost identical to the previous, end exists only because
1681  * yuy2ToY/UV)(dst, src+1, ...) would have 100% unaligned accesses. */
1682 static void uyvyToY_c(uint8_t *dst, const uint8_t *src, int width,
1683                       uint32_t *unused)
1684 {
1685     int i;
1686     for (i=0; i<width; i++)
1687         dst[i]= src[2*i+1];
1688 }
1689
1690 static void uyvyToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1691                        const uint8_t *src2, int width, uint32_t *unused)
1692 {
1693     int i;
1694     for (i=0; i<width; i++) {
1695         dstU[i]= src1[4*i + 0];
1696         dstV[i]= src1[4*i + 2];
1697     }
1698     assert(src1 == src2);
1699 }
1700
1701 static av_always_inline void nvXXtoUV_c(uint8_t *dst1, uint8_t *dst2,
1702                                         const uint8_t *src, int width)
1703 {
1704     int i;
1705     for (i = 0; i < width; i++) {
1706         dst1[i] = src[2*i+0];
1707         dst2[i] = src[2*i+1];
1708     }
1709 }
1710
1711 static void nv12ToUV_c(uint8_t *dstU, uint8_t *dstV,
1712                        const uint8_t *src1, const uint8_t *src2,
1713                        int width, uint32_t *unused)
1714 {
1715     nvXXtoUV_c(dstU, dstV, src1, width);
1716 }
1717
1718 static void nv21ToUV_c(uint8_t *dstU, uint8_t *dstV,
1719                        const uint8_t *src1, const uint8_t *src2,
1720                        int width, uint32_t *unused)
1721 {
1722     nvXXtoUV_c(dstV, dstU, src1, width);
1723 }
1724
1725 #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos))
1726
1727 static void bgr24ToY_c(uint8_t *dst, const uint8_t *src,
1728                        int width, uint32_t *unused)
1729 {
1730     int i;
1731     for (i=0; i<width; i++) {
1732         int b= src[i*3+0];
1733         int g= src[i*3+1];
1734         int r= src[i*3+2];
1735
1736         dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
1737     }
1738 }
1739
1740 static void bgr24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1741                         const uint8_t *src2, int width, uint32_t *unused)
1742 {
1743     int i;
1744     for (i=0; i<width; i++) {
1745         int b= src1[3*i + 0];
1746         int g= src1[3*i + 1];
1747         int r= src1[3*i + 2];
1748
1749         dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
1750         dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
1751     }
1752     assert(src1 == src2);
1753 }
1754
1755 static void bgr24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1756                              const uint8_t *src2, int width, uint32_t *unused)
1757 {
1758     int i;
1759     for (i=0; i<width; i++) {
1760         int b= src1[6*i + 0] + src1[6*i + 3];
1761         int g= src1[6*i + 1] + src1[6*i + 4];
1762         int r= src1[6*i + 2] + src1[6*i + 5];
1763
1764         dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
1765         dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
1766     }
1767     assert(src1 == src2);
1768 }
1769
1770 static void rgb24ToY_c(uint8_t *dst, const uint8_t *src, int width,
1771                        uint32_t *unused)
1772 {
1773     int i;
1774     for (i=0; i<width; i++) {
1775         int r= src[i*3+0];
1776         int g= src[i*3+1];
1777         int b= src[i*3+2];
1778
1779         dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
1780     }
1781 }
1782
1783 static void rgb24ToUV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1784                         const uint8_t *src2, int width, uint32_t *unused)
1785 {
1786     int i;
1787     assert(src1==src2);
1788     for (i=0; i<width; i++) {
1789         int r= src1[3*i + 0];
1790         int g= src1[3*i + 1];
1791         int b= src1[3*i + 2];
1792
1793         dstU[i]= (RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
1794         dstV[i]= (RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT;
1795     }
1796 }
1797
1798 static void rgb24ToUV_half_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *src1,
1799                              const uint8_t *src2, int width, uint32_t *unused)
1800 {
1801     int i;
1802     assert(src1==src2);
1803     for (i=0; i<width; i++) {
1804         int r= src1[6*i + 0] + src1[6*i + 3];
1805         int g= src1[6*i + 1] + src1[6*i + 4];
1806         int b= src1[6*i + 2] + src1[6*i + 5];
1807
1808         dstU[i]= (RU*r + GU*g + BU*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
1809         dstV[i]= (RV*r + GV*g + BV*b + (257<<RGB2YUV_SHIFT))>>(RGB2YUV_SHIFT+1);
1810     }
1811 }
1812
1813 static void planar_rgb_to_y(uint8_t *dst, const uint8_t *src[4], int width)
1814 {
1815     int i;
1816     for (i = 0; i < width; i++) {
1817         int g = src[0][i];
1818         int b = src[1][i];
1819         int r = src[2][i];
1820
1821         dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
1822     }
1823 }
1824
1825 static void planar_rgb16le_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
1826 {
1827     int i;
1828     const uint16_t **src = (const uint16_t **) _src;
1829     uint16_t *dst = (uint16_t *) _dst;
1830     for (i = 0; i < width; i++) {
1831         int g = AV_RL16(src[0] + i);
1832         int b = AV_RL16(src[1] + i);
1833         int r = AV_RL16(src[2] + i);
1834
1835         dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
1836     }
1837 }
1838
1839 static void planar_rgb16be_to_y(uint8_t *_dst, const uint8_t *_src[4], int width)
1840 {
1841     int i;
1842     const uint16_t **src = (const uint16_t **) _src;
1843     uint16_t *dst = (uint16_t *) _dst;
1844     for (i = 0; i < width; i++) {
1845         int g = AV_RB16(src[0] + i);
1846         int b = AV_RB16(src[1] + i);
1847         int r = AV_RB16(src[2] + i);
1848
1849         dst[i] = ((RY * r + GY * g + BY * b + (33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
1850     }
1851 }
1852
1853 static void planar_rgb_to_uv(uint8_t *dstU, uint8_t *dstV, const uint8_t *src[4], int width)
1854 {
1855     int i;
1856     for (i = 0; i < width; i++) {
1857         int g = src[0][i];
1858         int b = src[1][i];
1859         int r = src[2][i];
1860
1861         dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1862         dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1863     }
1864 }
1865
1866 static void planar_rgb16le_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
1867 {
1868     int i;
1869     const uint16_t **src = (const uint16_t **) _src;
1870     uint16_t *dstU = (uint16_t *) _dstU;
1871     uint16_t *dstV = (uint16_t *) _dstV;
1872     for (i = 0; i < width; i++) {
1873         int g = AV_RL16(src[0] + i);
1874         int b = AV_RL16(src[1] + i);
1875         int r = AV_RL16(src[2] + i);
1876
1877         dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1878         dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1879     }
1880 }
1881
1882 static void planar_rgb16be_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width)
1883 {
1884     int i;
1885     const uint16_t **src = (const uint16_t **) _src;
1886     uint16_t *dstU = (uint16_t *) _dstU;
1887     uint16_t *dstV = (uint16_t *) _dstV;
1888     for (i = 0; i < width; i++) {
1889         int g = AV_RB16(src[0] + i);
1890         int b = AV_RB16(src[1] + i);
1891         int r = AV_RB16(src[2] + i);
1892
1893         dstU[i] = (RU * r + GU * g + BU * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1894         dstV[i] = (RV * r + GV * g + BV * b + (257 << RGB2YUV_SHIFT)) >> (RGB2YUV_SHIFT + 1);
1895     }
1896 }
1897
1898 static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src,
1899                            const int16_t *filter,
1900                            const int16_t *filterPos, int filterSize)
1901 {
1902     int i;
1903     int32_t *dst = (int32_t *) _dst;
1904     const uint16_t *src = (const uint16_t *) _src;
1905     int bits = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
1906     int sh = bits - 4;
1907
1908     for (i = 0; i < dstW; i++) {
1909         int j;
1910         int srcPos = filterPos[i];
1911         int val = 0;
1912
1913         for (j = 0; j < filterSize; j++) {
1914             val += src[srcPos + j] * filter[filterSize * i + j];
1915         }
1916         // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
1917         dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
1918     }
1919 }
1920
1921 static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *_src,
1922                            const int16_t *filter,
1923                            const int16_t *filterPos, int filterSize)
1924 {
1925     int i;
1926     const uint16_t *src = (const uint16_t *) _src;
1927     int sh = av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
1928
1929     for (i = 0; i < dstW; i++) {
1930         int j;
1931         int srcPos = filterPos[i];
1932         int val = 0;
1933
1934         for (j = 0; j < filterSize; j++) {
1935             val += src[srcPos + j] * filter[filterSize * i + j];
1936         }
1937         // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
1938         dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
1939     }
1940 }
1941
1942 // bilinear / bicubic scaling
1943 static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
1944                           const int16_t *filter, const int16_t *filterPos,
1945                           int filterSize)
1946 {
1947     int i;
1948     for (i=0; i<dstW; i++) {
1949         int j;
1950         int srcPos= filterPos[i];
1951         int val=0;
1952         for (j=0; j<filterSize; j++) {
1953             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
1954         }
1955         //filter += hFilterSize;
1956         dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ...
1957         //dst[i] = val>>7;
1958     }
1959 }
1960
1961 static void hScale8To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *src,
1962                           const int16_t *filter, const int16_t *filterPos,
1963                           int filterSize)
1964 {
1965     int i;
1966     int32_t *dst = (int32_t *) _dst;
1967     for (i=0; i<dstW; i++) {
1968         int j;
1969         int srcPos= filterPos[i];
1970         int val=0;
1971         for (j=0; j<filterSize; j++) {
1972             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
1973         }
1974         //filter += hFilterSize;
1975         dst[i] = FFMIN(val>>3, (1<<19)-1); // the cubic equation does overflow ...
1976         //dst[i] = val>>7;
1977     }
1978 }
1979
1980 //FIXME all pal and rgb srcFormats could do this convertion as well
1981 //FIXME all scalers more complex than bilinear could do half of this transform
1982 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
1983 {
1984     int i;
1985     for (i = 0; i < width; i++) {
1986         dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264
1987         dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264
1988     }
1989 }
1990 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
1991 {
1992     int i;
1993     for (i = 0; i < width; i++) {
1994         dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469
1995         dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469
1996     }
1997 }
1998 static void lumRangeToJpeg_c(int16_t *dst, int width)
1999 {
2000     int i;
2001     for (i = 0; i < width; i++)
2002         dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14;
2003 }
2004 static void lumRangeFromJpeg_c(int16_t *dst, int width)
2005 {
2006     int i;
2007     for (i = 0; i < width; i++)
2008         dst[i] = (dst[i]*14071 + 33561947)>>14;
2009 }
2010
2011 static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
2012 {
2013     int i;
2014     int32_t *dstU = (int32_t *) _dstU;
2015     int32_t *dstV = (int32_t *) _dstV;
2016     for (i = 0; i < width; i++) {
2017         dstU[i] = (FFMIN(dstU[i],30775<<4)*4663 - (9289992<<4))>>12; //-264
2018         dstV[i] = (FFMIN(dstV[i],30775<<4)*4663 - (9289992<<4))>>12; //-264
2019     }
2020 }
2021 static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
2022 {
2023     int i;
2024     int32_t *dstU = (int32_t *) _dstU;
2025     int32_t *dstV = (int32_t *) _dstV;
2026     for (i = 0; i < width; i++) {
2027         dstU[i] = (dstU[i]*1799 + (4081085<<4))>>11; //1469
2028         dstV[i] = (dstV[i]*1799 + (4081085<<4))>>11; //1469
2029     }
2030 }
2031 static void lumRangeToJpeg16_c(int16_t *_dst, int width)
2032 {
2033     int i;
2034     int32_t *dst = (int32_t *) _dst;
2035     for (i = 0; i < width; i++)
2036         dst[i] = (FFMIN(dst[i],30189<<4)*4769 - (39057361<<2))>>12;
2037 }
2038 static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
2039 {
2040     int i;
2041     int32_t *dst = (int32_t *) _dst;
2042     for (i = 0; i < width; i++)
2043         dst[i] = (dst[i]*14071 + (33561947<<4))>>14;
2044 }
2045
2046 static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
2047                            const uint8_t *src, int srcW, int xInc)
2048 {
2049     int i;
2050     unsigned int xpos=0;
2051     for (i=0;i<dstWidth;i++) {
2052         register unsigned int xx=xpos>>16;
2053         register unsigned int xalpha=(xpos&0xFFFF)>>9;
2054         dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
2055         xpos+=xInc;
2056     }
2057 }
2058
2059 // *** horizontal scale Y line to temp buffer
2060 static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
2061                                      const uint8_t *src_in[4], int srcW, int xInc,
2062                                      const int16_t *hLumFilter,
2063                                      const int16_t *hLumFilterPos, int hLumFilterSize,
2064                                      uint8_t *formatConvBuffer,
2065                                      uint32_t *pal, int isAlpha)
2066 {
2067     void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
2068     void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
2069     const uint8_t *src = src_in[isAlpha ? 3 : 0];
2070
2071     if (toYV12) {
2072         toYV12(formatConvBuffer, src, srcW, pal);
2073         src= formatConvBuffer;
2074     } else if (c->readLumPlanar && !isAlpha) {
2075         c->readLumPlanar(formatConvBuffer, src_in, srcW);
2076         src = formatConvBuffer;
2077     }
2078
2079     if (!c->hyscale_fast) {
2080         c->hyScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
2081     } else { // fast bilinear upscale / crap downscale
2082         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
2083     }
2084
2085     if (convertRange)
2086         convertRange(dst, dstWidth);
2087 }
2088
2089 static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
2090                            int dstWidth, const uint8_t *src1,
2091                            const uint8_t *src2, int srcW, int xInc)
2092 {
2093     int i;
2094     unsigned int xpos=0;
2095     for (i=0;i<dstWidth;i++) {
2096         register unsigned int xx=xpos>>16;
2097         register unsigned int xalpha=(xpos&0xFFFF)>>9;
2098         dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
2099         dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
2100         xpos+=xInc;
2101     }
2102 }
2103
2104 static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth,
2105                                      const uint8_t *src_in[4],
2106                                      int srcW, int xInc, const int16_t *hChrFilter,
2107                                      const int16_t *hChrFilterPos, int hChrFilterSize,
2108                                      uint8_t *formatConvBuffer, uint32_t *pal)
2109 {
2110     const uint8_t *src1 = src_in[1], *src2 = src_in[2];
2111     if (c->chrToYV12) {
2112         uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
2113         c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
2114         src1= formatConvBuffer;
2115         src2= buf2;
2116     } else if (c->readChrPlanar) {
2117         uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW * FFALIGN(c->srcBpc, 8) >> 3, 16);
2118         c->readChrPlanar(formatConvBuffer, buf2, src_in, srcW);
2119         src1= formatConvBuffer;
2120         src2= buf2;
2121     }
2122
2123     if (!c->hcscale_fast) {
2124         c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
2125         c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
2126     } else { // fast bilinear upscale / crap downscale
2127         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
2128     }
2129
2130     if (c->chrConvertRange)
2131         c->chrConvertRange(dst1, dst2, dstWidth);
2132 }
2133
2134 static av_always_inline void
2135 find_c_packed_planar_out_funcs(SwsContext *c,
2136                                yuv2planar1_fn *yuv2plane1, yuv2planarX_fn *yuv2planeX,
2137                                yuv2interleavedX_fn *yuv2nv12cX,
2138                                yuv2packed1_fn *yuv2packed1, yuv2packed2_fn *yuv2packed2,
2139                                yuv2packedX_fn *yuv2packedX)
2140 {
2141     enum PixelFormat dstFormat = c->dstFormat;
2142
2143     if (is16BPS(dstFormat)) {
2144         *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c  : yuv2planeX_16LE_c;
2145         *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c  : yuv2plane1_16LE_c;
2146     } else if (is9_OR_10BPS(dstFormat)) {
2147         if (av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1 == 8) {
2148             *yuv2planeX = isBE(dstFormat) ? yuv2planeX_9BE_c  : yuv2planeX_9LE_c;
2149             *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_9BE_c  : yuv2plane1_9LE_c;
2150         } else {
2151             *yuv2planeX = isBE(dstFormat) ? yuv2planeX_10BE_c  : yuv2planeX_10LE_c;
2152             *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_10BE_c  : yuv2plane1_10LE_c;
2153         }
2154     } else {
2155         *yuv2plane1 = yuv2plane1_8_c;
2156         *yuv2planeX = yuv2planeX_8_c;
2157         if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)
2158             *yuv2nv12cX = yuv2nv12cX_c;
2159     }
2160
2161     if(c->flags & SWS_FULL_CHR_H_INT) {
2162         switch (dstFormat) {
2163             case PIX_FMT_RGBA:
2164 #if CONFIG_SMALL
2165                 *yuv2packedX = yuv2rgba32_full_X_c;
2166 #else
2167 #if CONFIG_SWSCALE_ALPHA
2168                 if (c->alpPixBuf) {
2169                     *yuv2packedX = yuv2rgba32_full_X_c;
2170                 } else
2171 #endif /* CONFIG_SWSCALE_ALPHA */
2172                 {
2173                     *yuv2packedX = yuv2rgbx32_full_X_c;
2174                 }
2175 #endif /* !CONFIG_SMALL */
2176                 break;
2177             case PIX_FMT_ARGB:
2178 #if CONFIG_SMALL
2179                 *yuv2packedX = yuv2argb32_full_X_c;
2180 #else
2181 #if CONFIG_SWSCALE_ALPHA
2182                 if (c->alpPixBuf) {
2183                     *yuv2packedX = yuv2argb32_full_X_c;
2184                 } else
2185 #endif /* CONFIG_SWSCALE_ALPHA */
2186                 {
2187                     *yuv2packedX = yuv2xrgb32_full_X_c;
2188                 }
2189 #endif /* !CONFIG_SMALL */
2190                 break;
2191             case PIX_FMT_BGRA:
2192 #if CONFIG_SMALL
2193                 *yuv2packedX = yuv2bgra32_full_X_c;
2194 #else
2195 #if CONFIG_SWSCALE_ALPHA
2196                 if (c->alpPixBuf) {
2197                     *yuv2packedX = yuv2bgra32_full_X_c;
2198                 } else
2199 #endif /* CONFIG_SWSCALE_ALPHA */
2200                 {
2201                     *yuv2packedX = yuv2bgrx32_full_X_c;
2202                 }
2203 #endif /* !CONFIG_SMALL */
2204                 break;
2205             case PIX_FMT_ABGR:
2206 #if CONFIG_SMALL
2207                 *yuv2packedX = yuv2abgr32_full_X_c;
2208 #else
2209 #if CONFIG_SWSCALE_ALPHA
2210                 if (c->alpPixBuf) {
2211                     *yuv2packedX = yuv2abgr32_full_X_c;
2212                 } else
2213 #endif /* CONFIG_SWSCALE_ALPHA */
2214                 {
2215                     *yuv2packedX = yuv2xbgr32_full_X_c;
2216                 }
2217 #endif /* !CONFIG_SMALL */
2218                 break;
2219             case PIX_FMT_RGB24:
2220             *yuv2packedX = yuv2rgb24_full_X_c;
2221             break;
2222         case PIX_FMT_BGR24:
2223             *yuv2packedX = yuv2bgr24_full_X_c;
2224             break;
2225         }
2226     } else {
2227         switch (dstFormat) {
2228         case PIX_FMT_GRAY16BE:
2229             *yuv2packed1 = yuv2gray16BE_1_c;
2230             *yuv2packed2 = yuv2gray16BE_2_c;
2231             *yuv2packedX = yuv2gray16BE_X_c;
2232             break;
2233         case PIX_FMT_GRAY16LE:
2234             *yuv2packed1 = yuv2gray16LE_1_c;
2235             *yuv2packed2 = yuv2gray16LE_2_c;
2236             *yuv2packedX = yuv2gray16LE_X_c;
2237             break;
2238         case PIX_FMT_MONOWHITE:
2239             *yuv2packed1 = yuv2monowhite_1_c;
2240             *yuv2packed2 = yuv2monowhite_2_c;
2241             *yuv2packedX = yuv2monowhite_X_c;
2242             break;
2243         case PIX_FMT_MONOBLACK:
2244             *yuv2packed1 = yuv2monoblack_1_c;
2245             *yuv2packed2 = yuv2monoblack_2_c;
2246             *yuv2packedX = yuv2monoblack_X_c;
2247             break;
2248         case PIX_FMT_YUYV422:
2249             *yuv2packed1 = yuv2yuyv422_1_c;
2250             *yuv2packed2 = yuv2yuyv422_2_c;
2251             *yuv2packedX = yuv2yuyv422_X_c;
2252             break;
2253         case PIX_FMT_UYVY422:
2254             *yuv2packed1 = yuv2uyvy422_1_c;
2255             *yuv2packed2 = yuv2uyvy422_2_c;
2256             *yuv2packedX = yuv2uyvy422_X_c;
2257             break;
2258         case PIX_FMT_RGB48LE:
2259             *yuv2packed1 = yuv2rgb48le_1_c;
2260             *yuv2packed2 = yuv2rgb48le_2_c;
2261             *yuv2packedX = yuv2rgb48le_X_c;
2262             break;
2263         case PIX_FMT_RGB48BE:
2264             *yuv2packed1 = yuv2rgb48be_1_c;
2265             *yuv2packed2 = yuv2rgb48be_2_c;
2266             *yuv2packedX = yuv2rgb48be_X_c;
2267             break;
2268         case PIX_FMT_BGR48LE:
2269             *yuv2packed1 = yuv2bgr48le_1_c;
2270             *yuv2packed2 = yuv2bgr48le_2_c;
2271             *yuv2packedX = yuv2bgr48le_X_c;
2272             break;
2273         case PIX_FMT_BGR48BE:
2274             *yuv2packed1 = yuv2bgr48be_1_c;
2275             *yuv2packed2 = yuv2bgr48be_2_c;
2276             *yuv2packedX = yuv2bgr48be_X_c;
2277             break;
2278         case PIX_FMT_RGB32:
2279         case PIX_FMT_BGR32:
2280 #if CONFIG_SMALL
2281             *yuv2packed1 = yuv2rgb32_1_c;
2282             *yuv2packed2 = yuv2rgb32_2_c;
2283             *yuv2packedX = yuv2rgb32_X_c;
2284 #else
2285 #if CONFIG_SWSCALE_ALPHA
2286                 if (c->alpPixBuf) {
2287                     *yuv2packed1 = yuv2rgba32_1_c;
2288                     *yuv2packed2 = yuv2rgba32_2_c;
2289                     *yuv2packedX = yuv2rgba32_X_c;
2290                 } else
2291 #endif /* CONFIG_SWSCALE_ALPHA */
2292                 {
2293                     *yuv2packed1 = yuv2rgbx32_1_c;
2294                     *yuv2packed2 = yuv2rgbx32_2_c;
2295                     *yuv2packedX = yuv2rgbx32_X_c;
2296                 }
2297 #endif /* !CONFIG_SMALL */
2298             break;
2299         case PIX_FMT_RGB32_1:
2300         case PIX_FMT_BGR32_1:
2301 #if CONFIG_SMALL
2302                 *yuv2packed1 = yuv2rgb32_1_1_c;
2303                 *yuv2packed2 = yuv2rgb32_1_2_c;
2304                 *yuv2packedX = yuv2rgb32_1_X_c;
2305 #else
2306 #if CONFIG_SWSCALE_ALPHA
2307                 if (c->alpPixBuf) {
2308                     *yuv2packed1 = yuv2rgba32_1_1_c;
2309                     *yuv2packed2 = yuv2rgba32_1_2_c;
2310                     *yuv2packedX = yuv2rgba32_1_X_c;
2311                 } else
2312 #endif /* CONFIG_SWSCALE_ALPHA */
2313                 {
2314                     *yuv2packed1 = yuv2rgbx32_1_1_c;
2315                     *yuv2packed2 = yuv2rgbx32_1_2_c;
2316                     *yuv2packedX = yuv2rgbx32_1_X_c;
2317                 }
2318 #endif /* !CONFIG_SMALL */
2319                 break;
2320         case PIX_FMT_RGB24:
2321             *yuv2packed1 = yuv2rgb24_1_c;
2322             *yuv2packed2 = yuv2rgb24_2_c;
2323             *yuv2packedX = yuv2rgb24_X_c;
2324             break;
2325         case PIX_FMT_BGR24:
2326             *yuv2packed1 = yuv2bgr24_1_c;
2327             *yuv2packed2 = yuv2bgr24_2_c;
2328             *yuv2packedX = yuv2bgr24_X_c;
2329             break;
2330         case PIX_FMT_RGB565LE:
2331         case PIX_FMT_RGB565BE:
2332         case PIX_FMT_BGR565LE:
2333         case PIX_FMT_BGR565BE:
2334             *yuv2packed1 = yuv2rgb16_1_c;
2335             *yuv2packed2 = yuv2rgb16_2_c;
2336             *yuv2packedX = yuv2rgb16_X_c;
2337             break;
2338         case PIX_FMT_RGB555LE:
2339         case PIX_FMT_RGB555BE:
2340         case PIX_FMT_BGR555LE:
2341         case PIX_FMT_BGR555BE:
2342             *yuv2packed1 = yuv2rgb15_1_c;
2343             *yuv2packed2 = yuv2rgb15_2_c;
2344             *yuv2packedX = yuv2rgb15_X_c;
2345             break;
2346         case PIX_FMT_RGB444LE:
2347         case PIX_FMT_RGB444BE:
2348         case PIX_FMT_BGR444LE:
2349         case PIX_FMT_BGR444BE:
2350             *yuv2packed1 = yuv2rgb12_1_c;
2351             *yuv2packed2 = yuv2rgb12_2_c;
2352             *yuv2packedX = yuv2rgb12_X_c;
2353             break;
2354         case PIX_FMT_RGB8:
2355         case PIX_FMT_BGR8:
2356             *yuv2packed1 = yuv2rgb8_1_c;
2357             *yuv2packed2 = yuv2rgb8_2_c;
2358             *yuv2packedX = yuv2rgb8_X_c;
2359             break;
2360         case PIX_FMT_RGB4:
2361         case PIX_FMT_BGR4:
2362             *yuv2packed1 = yuv2rgb4_1_c;
2363             *yuv2packed2 = yuv2rgb4_2_c;
2364             *yuv2packedX = yuv2rgb4_X_c;
2365             break;
2366         case PIX_FMT_RGB4_BYTE:
2367         case PIX_FMT_BGR4_BYTE:
2368             *yuv2packed1 = yuv2rgb4b_1_c;
2369             *yuv2packed2 = yuv2rgb4b_2_c;
2370             *yuv2packedX = yuv2rgb4b_X_c;
2371             break;
2372         }
2373     }
2374 }
2375
2376 #define DEBUG_SWSCALE_BUFFERS 0
2377 #define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
2378
2379 static int swScale(SwsContext *c, const uint8_t* src[],
2380                    int srcStride[], int srcSliceY,
2381                    int srcSliceH, uint8_t* dst[], int dstStride[])
2382 {
2383     /* load a few things into local vars to make the code more readable? and faster */
2384     const int srcW= c->srcW;
2385     const int dstW= c->dstW;
2386     const int dstH= c->dstH;
2387     const int chrDstW= c->chrDstW;
2388     const int chrSrcW= c->chrSrcW;
2389     const int lumXInc= c->lumXInc;
2390     const int chrXInc= c->chrXInc;
2391     const enum PixelFormat dstFormat= c->dstFormat;
2392     const int flags= c->flags;
2393     int16_t *vLumFilterPos= c->vLumFilterPos;
2394     int16_t *vChrFilterPos= c->vChrFilterPos;
2395     int16_t *hLumFilterPos= c->hLumFilterPos;
2396     int16_t *hChrFilterPos= c->hChrFilterPos;
2397     int16_t *vLumFilter= c->vLumFilter;
2398     int16_t *vChrFilter= c->vChrFilter;
2399     int16_t *hLumFilter= c->hLumFilter;
2400     int16_t *hChrFilter= c->hChrFilter;
2401     int32_t *lumMmxFilter= c->lumMmxFilter;
2402     int32_t *chrMmxFilter= c->chrMmxFilter;
2403     int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
2404     const int vLumFilterSize= c->vLumFilterSize;
2405     const int vChrFilterSize= c->vChrFilterSize;
2406     const int hLumFilterSize= c->hLumFilterSize;
2407     const int hChrFilterSize= c->hChrFilterSize;
2408     int16_t **lumPixBuf= c->lumPixBuf;
2409     int16_t **chrUPixBuf= c->chrUPixBuf;
2410     int16_t **chrVPixBuf= c->chrVPixBuf;
2411     int16_t **alpPixBuf= c->alpPixBuf;
2412     const int vLumBufSize= c->vLumBufSize;
2413     const int vChrBufSize= c->vChrBufSize;
2414     uint8_t *formatConvBuffer= c->formatConvBuffer;
2415     const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
2416     const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
2417     int lastDstY;
2418     uint32_t *pal=c->pal_yuv;
2419     yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
2420     yuv2planarX_fn yuv2planeX = c->yuv2planeX;
2421     yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
2422     yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
2423     yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
2424     yuv2packedX_fn yuv2packedX = c->yuv2packedX;
2425     int should_dither = is9_OR_10BPS(c->srcFormat) || is16BPS(c->srcFormat);
2426
2427     /* vars which will change and which we need to store back in the context */
2428     int dstY= c->dstY;
2429     int lumBufIndex= c->lumBufIndex;
2430     int chrBufIndex= c->chrBufIndex;
2431     int lastInLumBuf= c->lastInLumBuf;
2432     int lastInChrBuf= c->lastInChrBuf;
2433
2434     if (isPacked(c->srcFormat)) {
2435         src[0]=
2436         src[1]=
2437         src[2]=
2438         src[3]= src[0];
2439         srcStride[0]=
2440         srcStride[1]=
2441         srcStride[2]=
2442         srcStride[3]= srcStride[0];
2443     }
2444     srcStride[1]<<= c->vChrDrop;
2445     srcStride[2]<<= c->vChrDrop;
2446
2447     DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
2448                   src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],
2449                   dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);
2450     DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
2451                    srcSliceY,    srcSliceH,    dstY,    dstH);
2452     DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
2453                    vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
2454
2455     if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
2456         static int warnedAlready=0; //FIXME move this into the context perhaps
2457         if (flags & SWS_PRINT_INFO && !warnedAlready) {
2458             av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
2459                    "         ->cannot do aligned memory accesses anymore\n");
2460             warnedAlready=1;
2461         }
2462     }
2463
2464     /* Note the user might start scaling the picture in the middle so this
2465        will not get executed. This is not really intended but works
2466        currently, so people might do it. */
2467     if (srcSliceY ==0) {
2468         lumBufIndex=-1;
2469         chrBufIndex=-1;
2470         dstY=0;
2471         lastInLumBuf= -1;
2472         lastInChrBuf= -1;
2473     }
2474
2475     if (!should_dither) {
2476         c->chrDither8 = c->lumDither8 = ff_sws_pb_64;
2477     }
2478     lastDstY= dstY;
2479
2480     for (;dstY < dstH; dstY++) {
2481         const int chrDstY= dstY>>c->chrDstVSubSample;
2482         uint8_t *dest[4] = {
2483             dst[0] + dstStride[0] * dstY,
2484             dst[1] + dstStride[1] * chrDstY,
2485             dst[2] + dstStride[2] * chrDstY,
2486             (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL,
2487         };
2488
2489         const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
2490         const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
2491         const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
2492         int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
2493         int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input
2494         int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
2495         int enough_lines;
2496
2497         //handle holes (FAST_BILINEAR & weird filters)
2498         if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
2499         if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
2500         assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
2501         assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
2502
2503         DEBUG_BUFFERS("dstY: %d\n", dstY);
2504         DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
2505                          firstLumSrcY,    lastLumSrcY,    lastInLumBuf);
2506         DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
2507                          firstChrSrcY,    lastChrSrcY,    lastInChrBuf);
2508
2509         // Do we have enough lines in this slice to output the dstY line
2510         enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);
2511
2512         if (!enough_lines) {
2513             lastLumSrcY = srcSliceY + srcSliceH - 1;
2514             lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
2515             DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
2516                                             lastLumSrcY, lastChrSrcY);
2517         }
2518
2519         //Do horizontal scaling
2520         while(lastInLumBuf < lastLumSrcY) {
2521             const uint8_t *src1[4] = {
2522                 src[0] + (lastInLumBuf + 1 - srcSliceY) * srcStride[0],
2523                 src[1] + (lastInLumBuf + 1 - srcSliceY) * srcStride[1],
2524                 src[2] + (lastInLumBuf + 1 - srcSliceY) * srcStride[2],
2525                 src[3] + (lastInLumBuf + 1 - srcSliceY) * srcStride[3],
2526             };
2527             lumBufIndex++;
2528             assert(lumBufIndex < 2*vLumBufSize);
2529             assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
2530             assert(lastInLumBuf + 1 - srcSliceY >= 0);
2531             hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
2532                     hLumFilter, hLumFilterPos, hLumFilterSize,
2533                     formatConvBuffer,
2534                     pal, 0);
2535             if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
2536                 hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src1, srcW,
2537                         lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
2538                         formatConvBuffer,
2539                         pal, 1);
2540             lastInLumBuf++;
2541             DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
2542                                lumBufIndex,    lastInLumBuf);
2543         }
2544         while(lastInChrBuf < lastChrSrcY) {
2545             const uint8_t *src1[4] = {
2546                 src[0] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[0],
2547                 src[1] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[1],
2548                 src[2] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[2],
2549                 src[3] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[3],
2550             };
2551             chrBufIndex++;
2552             assert(chrBufIndex < 2*vChrBufSize);
2553             assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
2554             assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);
2555             //FIXME replace parameters through context struct (some at least)
2556
2557             if (c->needs_hcscale)
2558                 hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
2559                           chrDstW, src1, chrSrcW, chrXInc,
2560                           hChrFilter, hChrFilterPos, hChrFilterSize,
2561                           formatConvBuffer, pal);
2562             lastInChrBuf++;
2563             DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
2564                                chrBufIndex,    lastInChrBuf);
2565         }
2566         //wrap buf index around to stay inside the ring buffer
2567         if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;
2568         if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;
2569         if (!enough_lines)
2570             break; //we can't output a dstY line so let's try with the next slice
2571
2572 #if HAVE_MMX
2573         updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
2574 #endif
2575         if (should_dither) {
2576             c->chrDither8 = dither_8x8_128[chrDstY & 7];
2577             c->lumDither8 = dither_8x8_128[dstY & 7];
2578         }
2579         if (dstY >= dstH-2) {
2580             // hmm looks like we can't use MMX here without overwriting this array's tail
2581             find_c_packed_planar_out_funcs(c, &yuv2plane1, &yuv2planeX,  &yuv2nv12cX,
2582                                            &yuv2packed1, &yuv2packed2, &yuv2packedX);
2583         }
2584
2585         {
2586             const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
2587             const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
2588             const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
2589             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
2590             if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
2591                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
2592
2593                 if (vLumFilterSize == 1) {
2594                     yuv2plane1(lumSrcPtr[0], dest[0], dstW, c->lumDither8, 0);
2595                 } else {
2596                     yuv2planeX(vLumFilter + dstY * vLumFilterSize, vLumFilterSize,
2597                                lumSrcPtr, dest[0], dstW, c->lumDither8, 0);
2598                 }
2599
2600                 if (!((dstY&chrSkipMask) || isGray(dstFormat))) {
2601                     if (yuv2nv12cX) {
2602                         yuv2nv12cX(c, vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize, chrUSrcPtr, chrVSrcPtr, dest[1], chrDstW);
2603                     } else if (vChrFilterSize == 1) {
2604                         yuv2plane1(chrUSrcPtr[0], dest[1], chrDstW, c->chrDither8, 0);
2605                         yuv2plane1(chrVSrcPtr[0], dest[2], chrDstW, c->chrDither8, 3);
2606                     } else {
2607                         yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize,
2608                                    chrUSrcPtr, dest[1], chrDstW, c->chrDither8, 0);
2609                         yuv2planeX(vChrFilter + chrDstY * vChrFilterSize, vChrFilterSize,
2610                                    chrVSrcPtr, dest[2], chrDstW, c->chrDither8, 3);
2611                     }
2612                 }
2613
2614                 if (CONFIG_SWSCALE_ALPHA && alpPixBuf){
2615                     if (vLumFilterSize == 1) {
2616                         yuv2plane1(alpSrcPtr[0], dest[3], dstW, c->lumDither8, 0);
2617                     } else {
2618                         yuv2planeX(vLumFilter + dstY * vLumFilterSize, vLumFilterSize,
2619                                    alpSrcPtr, dest[3], dstW, c->lumDither8, 0);
2620                     }
2621                 }
2622             } else {
2623                 assert(lumSrcPtr  + vLumFilterSize - 1 < lumPixBuf  + vLumBufSize*2);
2624                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
2625                 if (c->yuv2packed1 && vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB
2626                     int chrAlpha = vChrFilter[2 * dstY + 1];
2627                     yuv2packed1(c, *lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
2628                                 alpPixBuf ? *alpSrcPtr : NULL,
2629                                 dest[0], dstW, chrAlpha, dstY);
2630                 } else if (c->yuv2packed2 && vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB
2631                     int lumAlpha = vLumFilter[2 * dstY + 1];
2632                     int chrAlpha = vChrFilter[2 * dstY + 1];
2633                     lumMmxFilter[2] =
2634                     lumMmxFilter[3] = vLumFilter[2 * dstY   ] * 0x10001;
2635                     chrMmxFilter[2] =
2636                     chrMmxFilter[3] = vChrFilter[2 * chrDstY] * 0x10001;
2637                     yuv2packed2(c, lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
2638                                 alpPixBuf ? alpSrcPtr : NULL,
2639                                 dest[0], dstW, lumAlpha, chrAlpha, dstY);
2640                 } else { //general RGB
2641                     yuv2packedX(c, vLumFilter + dstY * vLumFilterSize,
2642                                 lumSrcPtr, vLumFilterSize,
2643                                 vChrFilter + dstY * vChrFilterSize,
2644                                 chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
2645                                 alpSrcPtr, dest[0], dstW, dstY);
2646                 }
2647             }
2648         }
2649     }
2650
2651     if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)
2652         fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);
2653
2654 #if HAVE_MMX2
2655     if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
2656         __asm__ volatile("sfence":::"memory");
2657 #endif
2658     emms_c();
2659
2660     /* store changed local vars back in the context */
2661     c->dstY= dstY;
2662     c->lumBufIndex= lumBufIndex;
2663     c->chrBufIndex= chrBufIndex;
2664     c->lastInLumBuf= lastInLumBuf;
2665     c->lastInChrBuf= lastInChrBuf;
2666
2667     return dstY - lastDstY;
2668 }
2669
2670 static av_cold void sws_init_swScale_c(SwsContext *c)
2671 {
2672     enum PixelFormat srcFormat = c->srcFormat;
2673
2674     find_c_packed_planar_out_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
2675                                    &c->yuv2nv12cX, &c->yuv2packed1, &c->yuv2packed2,
2676                                    &c->yuv2packedX);
2677
2678     c->chrToYV12 = NULL;
2679     switch(srcFormat) {
2680         case PIX_FMT_YUYV422  : c->chrToYV12 = yuy2ToUV_c; break;
2681         case PIX_FMT_UYVY422  : c->chrToYV12 = uyvyToUV_c; break;
2682         case PIX_FMT_NV12     : c->chrToYV12 = nv12ToUV_c; break;
2683         case PIX_FMT_NV21     : c->chrToYV12 = nv21ToUV_c; break;
2684         case PIX_FMT_RGB8     :
2685         case PIX_FMT_BGR8     :
2686         case PIX_FMT_PAL8     :
2687         case PIX_FMT_BGR4_BYTE:
2688         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
2689         case PIX_FMT_GBRP9LE:
2690         case PIX_FMT_GBRP10LE:
2691         case PIX_FMT_GBRP16LE:  c->readChrPlanar = planar_rgb16le_to_uv; break;
2692         case PIX_FMT_GBRP9BE:
2693         case PIX_FMT_GBRP10BE:
2694         case PIX_FMT_GBRP16BE:  c->readChrPlanar = planar_rgb16be_to_uv; break;
2695         case PIX_FMT_GBRP:      c->readChrPlanar = planar_rgb_to_uv; break;
2696 #if HAVE_BIGENDIAN
2697         case PIX_FMT_YUV444P9LE:
2698         case PIX_FMT_YUV422P9LE:
2699         case PIX_FMT_YUV420P9LE:
2700         case PIX_FMT_YUV422P10LE:
2701         case PIX_FMT_YUV444P10LE:
2702         case PIX_FMT_YUV420P10LE:
2703         case PIX_FMT_YUV420P16LE:
2704         case PIX_FMT_YUV422P16LE:
2705         case PIX_FMT_YUV444P16LE: c->chrToYV12 = bswap16UV_c; break;
2706 #else
2707         case PIX_FMT_YUV444P9BE:
2708         case PIX_FMT_YUV422P9BE:
2709         case PIX_FMT_YUV420P9BE:
2710         case PIX_FMT_YUV444P10BE:
2711         case PIX_FMT_YUV422P10BE:
2712         case PIX_FMT_YUV420P10BE:
2713         case PIX_FMT_YUV420P16BE:
2714         case PIX_FMT_YUV422P16BE:
2715         case PIX_FMT_YUV444P16BE: c->chrToYV12 = bswap16UV_c; break;
2716 #endif
2717     }
2718     if (c->chrSrcHSubSample) {
2719         switch(srcFormat) {
2720         case PIX_FMT_RGB48BE : c->chrToYV12 = rgb48BEToUV_half_c; break;
2721         case PIX_FMT_RGB48LE : c->chrToYV12 = rgb48LEToUV_half_c; break;
2722         case PIX_FMT_BGR48BE : c->chrToYV12 = bgr48BEToUV_half_c; break;
2723         case PIX_FMT_BGR48LE : c->chrToYV12 = bgr48LEToUV_half_c; break;
2724         case PIX_FMT_RGB32   : c->chrToYV12 = bgr32ToUV_half_c;   break;
2725         case PIX_FMT_RGB32_1 : c->chrToYV12 = bgr321ToUV_half_c;  break;
2726         case PIX_FMT_BGR24   : c->chrToYV12 = bgr24ToUV_half_c;   break;
2727         case PIX_FMT_BGR565LE: c->chrToYV12 = bgr16leToUV_half_c; break;
2728         case PIX_FMT_BGR565BE: c->chrToYV12 = bgr16beToUV_half_c; break;
2729         case PIX_FMT_BGR555LE: c->chrToYV12 = bgr15leToUV_half_c; break;
2730         case PIX_FMT_BGR555BE: c->chrToYV12 = bgr15beToUV_half_c; break;
2731         case PIX_FMT_BGR32   : c->chrToYV12 = rgb32ToUV_half_c;   break;
2732         case PIX_FMT_BGR32_1 : c->chrToYV12 = rgb321ToUV_half_c;  break;
2733         case PIX_FMT_RGB24   : c->chrToYV12 = rgb24ToUV_half_c;   break;
2734         case PIX_FMT_RGB565LE: c->chrToYV12 = rgb16leToUV_half_c; break;
2735         case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_half_c; break;
2736         case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_half_c; break;
2737         case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_half_c; break;
2738         }
2739     } else {
2740         switch(srcFormat) {
2741         case PIX_FMT_RGB48BE : c->chrToYV12 = rgb48BEToUV_c; break;
2742         case PIX_FMT_RGB48LE : c->chrToYV12 = rgb48LEToUV_c; break;
2743         case PIX_FMT_BGR48BE : c->chrToYV12 = bgr48BEToUV_c; break;
2744         case PIX_FMT_BGR48LE : c->chrToYV12 = bgr48LEToUV_c; break;
2745         case PIX_FMT_RGB32   : c->chrToYV12 = bgr32ToUV_c;   break;
2746         case PIX_FMT_RGB32_1 : c->chrToYV12 = bgr321ToUV_c;  break;
2747         case PIX_FMT_BGR24   : c->chrToYV12 = bgr24ToUV_c;   break;
2748         case PIX_FMT_BGR565LE: c->chrToYV12 = bgr16leToUV_c; break;
2749         case PIX_FMT_BGR565BE: c->chrToYV12 = bgr16beToUV_c; break;
2750         case PIX_FMT_BGR555LE: c->chrToYV12 = bgr15leToUV_c; break;
2751         case PIX_FMT_BGR555BE: c->chrToYV12 = bgr15beToUV_c; break;
2752         case PIX_FMT_BGR32   : c->chrToYV12 = rgb32ToUV_c;   break;
2753         case PIX_FMT_BGR32_1 : c->chrToYV12 = rgb321ToUV_c;  break;
2754         case PIX_FMT_RGB24   : c->chrToYV12 = rgb24ToUV_c;   break;
2755         case PIX_FMT_RGB565LE: c->chrToYV12 = rgb16leToUV_c; break;
2756         case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_c; break;
2757         case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_c; break;
2758         case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_c; break;
2759         }
2760     }
2761
2762     c->lumToYV12 = NULL;
2763     c->alpToYV12 = NULL;
2764     switch (srcFormat) {
2765     case PIX_FMT_GBRP9LE:
2766     case PIX_FMT_GBRP10LE:
2767     case PIX_FMT_GBRP16LE: c->readLumPlanar = planar_rgb16le_to_y; break;
2768     case PIX_FMT_GBRP9BE:
2769     case PIX_FMT_GBRP10BE:
2770     case PIX_FMT_GBRP16BE: c->readLumPlanar = planar_rgb16be_to_y; break;
2771     case PIX_FMT_GBRP:     c->readLumPlanar = planar_rgb_to_y; break;
2772 #if HAVE_BIGENDIAN
2773     case PIX_FMT_YUV444P9LE:
2774     case PIX_FMT_YUV422P9LE:
2775     case PIX_FMT_YUV420P9LE:
2776     case PIX_FMT_YUV444P10LE:
2777     case PIX_FMT_YUV422P10LE:
2778     case PIX_FMT_YUV420P10LE:
2779     case PIX_FMT_YUV420P16LE:
2780     case PIX_FMT_YUV422P16LE:
2781     case PIX_FMT_YUV444P16LE:
2782     case PIX_FMT_GRAY16LE: c->lumToYV12 = bswap16Y_c; break;
2783 #else
2784     case PIX_FMT_YUV444P9BE:
2785     case PIX_FMT_YUV422P9BE:
2786     case PIX_FMT_YUV420P9BE:
2787     case PIX_FMT_YUV444P10BE:
2788     case PIX_FMT_YUV422P10BE:
2789     case PIX_FMT_YUV420P10BE:
2790     case PIX_FMT_YUV420P16BE:
2791     case PIX_FMT_YUV422P16BE:
2792     case PIX_FMT_YUV444P16BE:
2793     case PIX_FMT_GRAY16BE: c->lumToYV12 = bswap16Y_c; break;
2794 #endif
2795     case PIX_FMT_YUYV422  :
2796     case PIX_FMT_Y400A    : c->lumToYV12 = yuy2ToY_c; break;
2797     case PIX_FMT_UYVY422  : c->lumToYV12 = uyvyToY_c;    break;
2798     case PIX_FMT_BGR24    : c->lumToYV12 = bgr24ToY_c;   break;
2799     case PIX_FMT_BGR565LE : c->lumToYV12 = bgr16leToY_c; break;
2800     case PIX_FMT_BGR565BE : c->lumToYV12 = bgr16beToY_c; break;
2801     case PIX_FMT_BGR555LE : c->lumToYV12 = bgr15leToY_c; break;
2802     case PIX_FMT_BGR555BE : c->lumToYV12 = bgr15beToY_c; break;
2803     case PIX_FMT_RGB24    : c->lumToYV12 = rgb24ToY_c;   break;
2804     case PIX_FMT_RGB565LE : c->lumToYV12 = rgb16leToY_c; break;
2805     case PIX_FMT_RGB565BE : c->lumToYV12 = rgb16beToY_c; break;
2806     case PIX_FMT_RGB555LE : c->lumToYV12 = rgb15leToY_c; break;
2807     case PIX_FMT_RGB555BE : c->lumToYV12 = rgb15beToY_c; break;
2808     case PIX_FMT_RGB8     :
2809     case PIX_FMT_BGR8     :
2810     case PIX_FMT_PAL8     :
2811     case PIX_FMT_BGR4_BYTE:
2812     case PIX_FMT_RGB4_BYTE: c->lumToYV12 = palToY_c; break;
2813     case PIX_FMT_MONOBLACK: c->lumToYV12 = monoblack2Y_c; break;
2814     case PIX_FMT_MONOWHITE: c->lumToYV12 = monowhite2Y_c; break;
2815     case PIX_FMT_RGB32  : c->lumToYV12 = bgr32ToY_c;  break;
2816     case PIX_FMT_RGB32_1: c->lumToYV12 = bgr321ToY_c; break;
2817     case PIX_FMT_BGR32  : c->lumToYV12 = rgb32ToY_c;  break;
2818     case PIX_FMT_BGR32_1: c->lumToYV12 = rgb321ToY_c; break;
2819     case PIX_FMT_RGB48BE: c->lumToYV12 = rgb48BEToY_c; break;
2820     case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY_c; break;
2821     case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY_c; break;
2822     case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY_c; break;
2823     }
2824     if (c->alpPixBuf) {
2825         switch (srcFormat) {
2826         case PIX_FMT_BGRA:
2827         case PIX_FMT_RGBA:  c->alpToYV12 = rgbaToA_c; break;
2828         case PIX_FMT_ABGR:
2829         case PIX_FMT_ARGB:  c->alpToYV12 = abgrToA_c; break;
2830         case PIX_FMT_Y400A: c->alpToYV12 = uyvyToY_c; break;
2831         }
2832     }
2833
2834     if (c->srcBpc == 8) {
2835         if (c->dstBpc <= 10) {
2836             c->hyScale = c->hcScale = hScale8To15_c;
2837             if (c->flags & SWS_FAST_BILINEAR) {
2838                 c->hyscale_fast = hyscale_fast_c;
2839                 c->hcscale_fast = hcscale_fast_c;
2840             }
2841         } else {
2842             c->hyScale = c->hcScale = hScale8To19_c;
2843         }
2844     } else {
2845         c->hyScale = c->hcScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c;
2846     }
2847
2848     if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
2849         if (c->dstBpc <= 10) {
2850             if (c->srcRange) {
2851                 c->lumConvertRange = lumRangeFromJpeg_c;
2852                 c->chrConvertRange = chrRangeFromJpeg_c;
2853             } else {
2854                 c->lumConvertRange = lumRangeToJpeg_c;
2855                 c->chrConvertRange = chrRangeToJpeg_c;
2856             }
2857         } else {
2858             if (c->srcRange) {
2859                 c->lumConvertRange = lumRangeFromJpeg16_c;
2860                 c->chrConvertRange = chrRangeFromJpeg16_c;
2861             } else {
2862                 c->lumConvertRange = lumRangeToJpeg16_c;
2863                 c->chrConvertRange = chrRangeToJpeg16_c;
2864             }
2865         }
2866     }
2867
2868     if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
2869           srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
2870         c->needs_hcscale = 1;
2871 }
2872
2873 SwsFunc ff_getSwsFunc(SwsContext *c)
2874 {
2875     sws_init_swScale_c(c);
2876
2877     if (HAVE_MMX)
2878         ff_sws_init_swScale_mmx(c);
2879     if (HAVE_ALTIVEC)
2880         ff_sws_init_swScale_altivec(c);
2881
2882     return swScale;
2883 }