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