OSDN Git Service

ALSA: fix use of period_size.
[coroid/ffmpeg_saccubus.git] / 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 // FIXME Maybe dither instead.
1787 static av_always_inline void
1788 yuv9_OR_10ToUV_c_template(uint8_t *dstU, uint8_t *dstV,
1789                           const uint8_t *_srcU, const uint8_t *_srcV,
1790                           int width, enum PixelFormat origin, int depth)
1791 {
1792     int i;
1793     const uint16_t *srcU = (const uint16_t *) _srcU;
1794     const uint16_t *srcV = (const uint16_t *) _srcV;
1795
1796     for (i = 0; i < width; i++) {
1797         dstU[i] = input_pixel(&srcU[i]) >> (depth - 8);
1798         dstV[i] = input_pixel(&srcV[i]) >> (depth - 8);
1799     }
1800 }
1801
1802 static av_always_inline void
1803 yuv9_or_10ToY_c_template(uint8_t *dstY, const uint8_t *_srcY,
1804                          int width, enum PixelFormat origin, int depth)
1805 {
1806     int i;
1807     const uint16_t *srcY = (const uint16_t*)_srcY;
1808
1809     for (i = 0; i < width; i++)
1810         dstY[i] = input_pixel(&srcY[i]) >> (depth - 8);
1811 }
1812
1813 #undef input_pixel
1814
1815 #define YUV_NBPS(depth, BE_LE, origin) \
1816 static void BE_LE ## depth ## ToUV_c(uint8_t *dstU, uint8_t *dstV, \
1817                                      const uint8_t *srcU, const uint8_t *srcV, \
1818                                      int width, uint32_t *unused) \
1819 { \
1820     yuv9_OR_10ToUV_c_template(dstU, dstV, srcU, srcV, width, origin, depth); \
1821 } \
1822 static void BE_LE ## depth ## ToY_c(uint8_t *dstY, const uint8_t *srcY, \
1823                                     int width, uint32_t *unused) \
1824 { \
1825     yuv9_or_10ToY_c_template(dstY, srcY, width, origin, depth); \
1826 }
1827
1828 YUV_NBPS( 9, LE, PIX_FMT_YUV420P9LE);
1829 YUV_NBPS( 9, BE, PIX_FMT_YUV420P9BE);
1830 YUV_NBPS(10, LE, PIX_FMT_YUV420P10LE);
1831 YUV_NBPS(10, BE, PIX_FMT_YUV420P10BE);
1832
1833 static void bgr24ToY_c(int16_t *dst, const uint8_t *src,
1834                        int width, uint32_t *unused)
1835 {
1836     int i;
1837     for (i=0; i<width; i++) {
1838         int b= src[i*3+0];
1839         int g= src[i*3+1];
1840         int r= src[i*3+2];
1841
1842         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
1843     }
1844 }
1845
1846 static void bgr24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
1847                         const uint8_t *src2, int width, uint32_t *unused)
1848 {
1849     int i;
1850     for (i=0; i<width; i++) {
1851         int b= src1[3*i + 0];
1852         int g= src1[3*i + 1];
1853         int r= src1[3*i + 2];
1854
1855         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
1856         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
1857     }
1858     assert(src1 == src2);
1859 }
1860
1861 static void bgr24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
1862                              const uint8_t *src2, int width, uint32_t *unused)
1863 {
1864     int i;
1865     for (i=0; i<width; i++) {
1866         int b= src1[6*i + 0] + src1[6*i + 3];
1867         int g= src1[6*i + 1] + src1[6*i + 4];
1868         int r= src1[6*i + 2] + src1[6*i + 5];
1869
1870         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
1871         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
1872     }
1873     assert(src1 == src2);
1874 }
1875
1876 static void rgb24ToY_c(int16_t *dst, const uint8_t *src, int width,
1877                        uint32_t *unused)
1878 {
1879     int i;
1880     for (i=0; i<width; i++) {
1881         int r= src[i*3+0];
1882         int g= src[i*3+1];
1883         int b= src[i*3+2];
1884
1885         dst[i]= ((RY*r + GY*g + BY*b + (32<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6));
1886     }
1887 }
1888
1889 static void rgb24ToUV_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
1890                         const uint8_t *src2, int width, uint32_t *unused)
1891 {
1892     int i;
1893     assert(src1==src2);
1894     for (i=0; i<width; i++) {
1895         int r= src1[3*i + 0];
1896         int g= src1[3*i + 1];
1897         int b= src1[3*i + 2];
1898
1899         dstU[i]= (RU*r + GU*g + BU*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
1900         dstV[i]= (RV*r + GV*g + BV*b + (256<<(RGB2YUV_SHIFT-1)) + (1<<(RGB2YUV_SHIFT-7)))>>(RGB2YUV_SHIFT-6);
1901     }
1902 }
1903
1904 static void rgb24ToUV_half_c(int16_t *dstU, int16_t *dstV, const uint8_t *src1,
1905                                     const uint8_t *src2, int width, uint32_t *unused)
1906 {
1907     int i;
1908     assert(src1==src2);
1909     for (i=0; i<width; i++) {
1910         int r= src1[6*i + 0] + src1[6*i + 3];
1911         int g= src1[6*i + 1] + src1[6*i + 4];
1912         int b= src1[6*i + 2] + src1[6*i + 5];
1913
1914         dstU[i]= (RU*r + GU*g + BU*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
1915         dstV[i]= (RV*r + GV*g + BV*b + (256<<RGB2YUV_SHIFT) + (1<<(RGB2YUV_SHIFT-6)))>>(RGB2YUV_SHIFT-5);
1916     }
1917 }
1918
1919 // bilinear / bicubic scaling
1920 static void hScale_c(int16_t *dst, int dstW, const uint8_t *src,
1921                      const int16_t *filter, const int16_t *filterPos,
1922                      int filterSize)
1923 {
1924     int i;
1925     for (i=0; i<dstW; i++) {
1926         int j;
1927         int srcPos= filterPos[i];
1928         int val=0;
1929         for (j=0; j<filterSize; j++) {
1930             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
1931         }
1932         //filter += hFilterSize;
1933         dst[i] = FFMIN(val>>7, (1<<15)-1); // the cubic equation does overflow ...
1934         //dst[i] = val>>7;
1935     }
1936 }
1937
1938 static inline void hScale16_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
1939                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
1940 {
1941     int i, j;
1942
1943     for (i=0; i<dstW; i++) {
1944         int srcPos= filterPos[i];
1945         int val=0;
1946         for (j=0; j<filterSize; j++) {
1947             val += ((int)src[srcPos + j])*filter[filterSize*i + j];
1948         }
1949         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
1950     }
1951 }
1952
1953 static inline void hScale16X_c(int16_t *dst, int dstW, const uint16_t *src, int srcW, int xInc,
1954                                     const int16_t *filter, const int16_t *filterPos, long filterSize, int shift)
1955 {
1956     int i, j;
1957     for (i=0; i<dstW; i++) {
1958         int srcPos= filterPos[i];
1959         int val=0;
1960         for (j=0; j<filterSize; j++) {
1961             val += ((int)av_bswap16(src[srcPos + j]))*filter[filterSize*i + j];
1962         }
1963         dst[i] = FFMIN(val>>shift, (1<<15)-1); // the cubic equation does overflow ...
1964     }
1965 }
1966
1967 //FIXME all pal and rgb srcFormats could do this convertion as well
1968 //FIXME all scalers more complex than bilinear could do half of this transform
1969 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
1970 {
1971     int i;
1972     for (i = 0; i < width; i++) {
1973         dstU[i] = (FFMIN(dstU[i],30775)*4663 - 9289992)>>12; //-264
1974         dstV[i] = (FFMIN(dstV[i],30775)*4663 - 9289992)>>12; //-264
1975     }
1976 }
1977 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
1978 {
1979     int i;
1980     for (i = 0; i < width; i++) {
1981         dstU[i] = (dstU[i]*1799 + 4081085)>>11; //1469
1982         dstV[i] = (dstV[i]*1799 + 4081085)>>11; //1469
1983     }
1984 }
1985 static void lumRangeToJpeg_c(int16_t *dst, int width)
1986 {
1987     int i;
1988     for (i = 0; i < width; i++)
1989         dst[i] = (FFMIN(dst[i],30189)*19077 - 39057361)>>14;
1990 }
1991 static void lumRangeFromJpeg_c(int16_t *dst, int width)
1992 {
1993     int i;
1994     for (i = 0; i < width; i++)
1995         dst[i] = (dst[i]*14071 + 33561947)>>14;
1996 }
1997
1998 static void hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
1999                            const uint8_t *src, int srcW, int xInc)
2000 {
2001     int i;
2002     unsigned int xpos=0;
2003     for (i=0;i<dstWidth;i++) {
2004         register unsigned int xx=xpos>>16;
2005         register unsigned int xalpha=(xpos&0xFFFF)>>9;
2006         dst[i]= (src[xx]<<7) + (src[xx+1] - src[xx])*xalpha;
2007         xpos+=xInc;
2008     }
2009     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
2010         dst[i] = src[srcW-1]*128;
2011 }
2012
2013 // *** horizontal scale Y line to temp buffer
2014 static av_always_inline void hyscale(SwsContext *c, uint16_t *dst, int dstWidth,
2015                                      const uint8_t *src, int srcW, int xInc,
2016                                      const int16_t *hLumFilter,
2017                                      const int16_t *hLumFilterPos, int hLumFilterSize,
2018                                      uint8_t *formatConvBuffer,
2019                                      uint32_t *pal, int isAlpha)
2020 {
2021     void (*toYV12)(uint8_t *, const uint8_t *, int, uint32_t *) = isAlpha ? c->alpToYV12 : c->lumToYV12;
2022     void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
2023
2024     if (toYV12) {
2025         toYV12(formatConvBuffer, src, srcW, pal);
2026         src= formatConvBuffer;
2027     }
2028
2029     if (c->hScale16) {
2030         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
2031         c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
2032     } else if (!c->hyscale_fast) {
2033         c->hScale(dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
2034     } else { // fast bilinear upscale / crap downscale
2035         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
2036     }
2037
2038     if (convertRange)
2039         convertRange(dst, dstWidth);
2040 }
2041
2042 static void hcscale_fast_c(SwsContext *c, int16_t *dst1, int16_t *dst2,
2043                            int dstWidth, const uint8_t *src1,
2044                            const uint8_t *src2, int srcW, int xInc)
2045 {
2046     int i;
2047     unsigned int xpos=0;
2048     for (i=0;i<dstWidth;i++) {
2049         register unsigned int xx=xpos>>16;
2050         register unsigned int xalpha=(xpos&0xFFFF)>>9;
2051         dst1[i]=(src1[xx]*(xalpha^127)+src1[xx+1]*xalpha);
2052         dst2[i]=(src2[xx]*(xalpha^127)+src2[xx+1]*xalpha);
2053         xpos+=xInc;
2054     }
2055     for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
2056         dst1[i] = src1[srcW-1]*128;
2057         dst2[i] = src2[srcW-1]*128;
2058     }
2059 }
2060
2061 static av_always_inline void hcscale(SwsContext *c, uint16_t *dst1, uint16_t *dst2, int dstWidth,
2062                                      const uint8_t *src1, const uint8_t *src2,
2063                                      int srcW, int xInc, const int16_t *hChrFilter,
2064                                      const int16_t *hChrFilterPos, int hChrFilterSize,
2065                                      uint8_t *formatConvBuffer, uint32_t *pal)
2066 {
2067     if (c->chrToYV12) {
2068         uint8_t *buf2 = formatConvBuffer + FFALIGN(srcW*2+78, 16);
2069         c->chrToYV12(formatConvBuffer, buf2, src1, src2, srcW, pal);
2070         src1= formatConvBuffer;
2071         src2= buf2;
2072     }
2073
2074     if (c->hScale16) {
2075         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
2076         c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
2077         c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
2078     } else if (!c->hcscale_fast) {
2079         c->hScale(dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
2080         c->hScale(dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
2081     } else { // fast bilinear upscale / crap downscale
2082         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
2083     }
2084
2085     if (c->chrConvertRange)
2086         c->chrConvertRange(dst1, dst2, dstWidth);
2087 }
2088
2089 static av_always_inline void
2090 find_c_packed_planar_out_funcs(SwsContext *c,
2091                                yuv2planar1_fn *yuv2yuv1,    yuv2planarX_fn *yuv2yuvX,
2092                                yuv2packed1_fn *yuv2packed1, yuv2packed2_fn *yuv2packed2,
2093                                yuv2packedX_fn *yuv2packedX)
2094 {
2095     enum PixelFormat dstFormat = c->dstFormat;
2096
2097     if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {
2098         *yuv2yuvX     = yuv2nv12X_c;
2099     } else if (is16BPS(dstFormat)) {
2100         *yuv2yuvX     = isBE(dstFormat) ? yuv2yuvX16BE_c  : yuv2yuvX16LE_c;
2101     } else if (is9_OR_10BPS(dstFormat)) {
2102         if (av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1 == 8) {
2103             *yuv2yuvX = isBE(dstFormat) ? yuv2yuvX9BE_c :  yuv2yuvX9LE_c;
2104         } else {
2105             *yuv2yuvX = isBE(dstFormat) ? yuv2yuvX10BE_c : yuv2yuvX10LE_c;
2106         }
2107     } else {
2108         *yuv2yuv1     = yuv2yuv1_c;
2109         *yuv2yuvX     = yuv2yuvX_c;
2110     }
2111     if(c->flags & SWS_FULL_CHR_H_INT) {
2112         switch (dstFormat) {
2113             case PIX_FMT_RGBA:
2114 #if CONFIG_SMALL
2115                 *yuv2packedX = yuv2rgba32_full_X_c;
2116 #else
2117 #if CONFIG_SWSCALE_ALPHA
2118                 if (c->alpPixBuf) {
2119                     *yuv2packedX = yuv2rgba32_full_X_c;
2120                 } else
2121 #endif /* CONFIG_SWSCALE_ALPHA */
2122                 {
2123                     *yuv2packedX = yuv2rgbx32_full_X_c;
2124                 }
2125 #endif /* !CONFIG_SMALL */
2126                 break;
2127             case PIX_FMT_ARGB:
2128 #if CONFIG_SMALL
2129                 *yuv2packedX = yuv2argb32_full_X_c;
2130 #else
2131 #if CONFIG_SWSCALE_ALPHA
2132                 if (c->alpPixBuf) {
2133                     *yuv2packedX = yuv2argb32_full_X_c;
2134                 } else
2135 #endif /* CONFIG_SWSCALE_ALPHA */
2136                 {
2137                     *yuv2packedX = yuv2xrgb32_full_X_c;
2138                 }
2139 #endif /* !CONFIG_SMALL */
2140                 break;
2141             case PIX_FMT_BGRA:
2142 #if CONFIG_SMALL
2143                 *yuv2packedX = yuv2bgra32_full_X_c;
2144 #else
2145 #if CONFIG_SWSCALE_ALPHA
2146                 if (c->alpPixBuf) {
2147                     *yuv2packedX = yuv2bgra32_full_X_c;
2148                 } else
2149 #endif /* CONFIG_SWSCALE_ALPHA */
2150                 {
2151                     *yuv2packedX = yuv2bgrx32_full_X_c;
2152                 }
2153 #endif /* !CONFIG_SMALL */
2154                 break;
2155             case PIX_FMT_ABGR:
2156 #if CONFIG_SMALL
2157                 *yuv2packedX = yuv2abgr32_full_X_c;
2158 #else
2159 #if CONFIG_SWSCALE_ALPHA
2160                 if (c->alpPixBuf) {
2161                     *yuv2packedX = yuv2abgr32_full_X_c;
2162                 } else
2163 #endif /* CONFIG_SWSCALE_ALPHA */
2164                 {
2165                     *yuv2packedX = yuv2xbgr32_full_X_c;
2166                 }
2167 #endif /* !CONFIG_SMALL */
2168                 break;
2169             case PIX_FMT_RGB24:
2170             *yuv2packedX = yuv2rgb24_full_X_c;
2171             break;
2172         case PIX_FMT_BGR24:
2173             *yuv2packedX = yuv2bgr24_full_X_c;
2174             break;
2175         }
2176         if(!*yuv2packedX)
2177             goto YUV_PACKED;
2178     } else {
2179         YUV_PACKED:
2180         switch (dstFormat) {
2181         case PIX_FMT_GRAY16BE:
2182             *yuv2packed1 = yuv2gray16BE_1_c;
2183             *yuv2packed2 = yuv2gray16BE_2_c;
2184             *yuv2packedX = yuv2gray16BE_X_c;
2185             break;
2186         case PIX_FMT_GRAY16LE:
2187             *yuv2packed1 = yuv2gray16LE_1_c;
2188             *yuv2packed2 = yuv2gray16LE_2_c;
2189             *yuv2packedX = yuv2gray16LE_X_c;
2190             break;
2191         case PIX_FMT_MONOWHITE:
2192             *yuv2packed1 = yuv2monowhite_1_c;
2193             *yuv2packed2 = yuv2monowhite_2_c;
2194             *yuv2packedX = yuv2monowhite_X_c;
2195             break;
2196         case PIX_FMT_MONOBLACK:
2197             *yuv2packed1 = yuv2monoblack_1_c;
2198             *yuv2packed2 = yuv2monoblack_2_c;
2199             *yuv2packedX = yuv2monoblack_X_c;
2200             break;
2201         case PIX_FMT_YUYV422:
2202             *yuv2packed1 = yuv2yuyv422_1_c;
2203             *yuv2packed2 = yuv2yuyv422_2_c;
2204             *yuv2packedX = yuv2yuyv422_X_c;
2205             break;
2206         case PIX_FMT_UYVY422:
2207             *yuv2packed1 = yuv2uyvy422_1_c;
2208             *yuv2packed2 = yuv2uyvy422_2_c;
2209             *yuv2packedX = yuv2uyvy422_X_c;
2210             break;
2211         case PIX_FMT_RGB48LE:
2212             //*yuv2packed1 = yuv2rgb48le_1_c;
2213             //*yuv2packed2 = yuv2rgb48le_2_c;
2214             //*yuv2packedX = yuv2rgb48le_X_c;
2215             //break;
2216         case PIX_FMT_RGB48BE:
2217             *yuv2packed1 = yuv2rgb48be_1_c;
2218             *yuv2packed2 = yuv2rgb48be_2_c;
2219             *yuv2packedX = yuv2rgb48be_X_c;
2220             break;
2221         case PIX_FMT_BGR48LE:
2222             //*yuv2packed1 = yuv2bgr48le_1_c;
2223             //*yuv2packed2 = yuv2bgr48le_2_c;
2224             //*yuv2packedX = yuv2bgr48le_X_c;
2225             //break;
2226         case PIX_FMT_BGR48BE:
2227             *yuv2packed1 = yuv2bgr48be_1_c;
2228             *yuv2packed2 = yuv2bgr48be_2_c;
2229             *yuv2packedX = yuv2bgr48be_X_c;
2230             break;
2231         case PIX_FMT_RGB32:
2232         case PIX_FMT_BGR32:
2233 #if CONFIG_SMALL
2234             *yuv2packed1 = yuv2rgb32_1_c;
2235             *yuv2packed2 = yuv2rgb32_2_c;
2236             *yuv2packedX = yuv2rgb32_X_c;
2237 #else
2238 #if CONFIG_SWSCALE_ALPHA
2239                 if (c->alpPixBuf) {
2240                     *yuv2packed1 = yuv2rgba32_1_c;
2241                     *yuv2packed2 = yuv2rgba32_2_c;
2242                     *yuv2packedX = yuv2rgba32_X_c;
2243                 } else
2244 #endif /* CONFIG_SWSCALE_ALPHA */
2245                 {
2246                     *yuv2packed1 = yuv2rgbx32_1_c;
2247                     *yuv2packed2 = yuv2rgbx32_2_c;
2248                     *yuv2packedX = yuv2rgbx32_X_c;
2249                 }
2250 #endif /* !CONFIG_SMALL */
2251             break;
2252         case PIX_FMT_RGB32_1:
2253         case PIX_FMT_BGR32_1:
2254 #if CONFIG_SMALL
2255                 *yuv2packed1 = yuv2rgb32_1_1_c;
2256                 *yuv2packed2 = yuv2rgb32_1_2_c;
2257                 *yuv2packedX = yuv2rgb32_1_X_c;
2258 #else
2259 #if CONFIG_SWSCALE_ALPHA
2260                 if (c->alpPixBuf) {
2261                     *yuv2packed1 = yuv2rgba32_1_1_c;
2262                     *yuv2packed2 = yuv2rgba32_1_2_c;
2263                     *yuv2packedX = yuv2rgba32_1_X_c;
2264                 } else
2265 #endif /* CONFIG_SWSCALE_ALPHA */
2266                 {
2267                     *yuv2packed1 = yuv2rgbx32_1_1_c;
2268                     *yuv2packed2 = yuv2rgbx32_1_2_c;
2269                     *yuv2packedX = yuv2rgbx32_1_X_c;
2270                 }
2271 #endif /* !CONFIG_SMALL */
2272                 break;
2273         case PIX_FMT_RGB24:
2274             *yuv2packed1 = yuv2rgb24_1_c;
2275             *yuv2packed2 = yuv2rgb24_2_c;
2276             *yuv2packedX = yuv2rgb24_X_c;
2277             break;
2278         case PIX_FMT_BGR24:
2279             *yuv2packed1 = yuv2bgr24_1_c;
2280             *yuv2packed2 = yuv2bgr24_2_c;
2281             *yuv2packedX = yuv2bgr24_X_c;
2282             break;
2283         case PIX_FMT_RGB565LE:
2284         case PIX_FMT_RGB565BE:
2285         case PIX_FMT_BGR565LE:
2286         case PIX_FMT_BGR565BE:
2287             *yuv2packed1 = yuv2rgb16_1_c;
2288             *yuv2packed2 = yuv2rgb16_2_c;
2289             *yuv2packedX = yuv2rgb16_X_c;
2290             break;
2291         case PIX_FMT_RGB555LE:
2292         case PIX_FMT_RGB555BE:
2293         case PIX_FMT_BGR555LE:
2294         case PIX_FMT_BGR555BE:
2295             *yuv2packed1 = yuv2rgb15_1_c;
2296             *yuv2packed2 = yuv2rgb15_2_c;
2297             *yuv2packedX = yuv2rgb15_X_c;
2298             break;
2299         case PIX_FMT_RGB444LE:
2300         case PIX_FMT_RGB444BE:
2301         case PIX_FMT_BGR444LE:
2302         case PIX_FMT_BGR444BE:
2303             *yuv2packed1 = yuv2rgb12_1_c;
2304             *yuv2packed2 = yuv2rgb12_2_c;
2305             *yuv2packedX = yuv2rgb12_X_c;
2306             break;
2307         case PIX_FMT_RGB8:
2308         case PIX_FMT_BGR8:
2309             *yuv2packed1 = yuv2rgb8_1_c;
2310             *yuv2packed2 = yuv2rgb8_2_c;
2311             *yuv2packedX = yuv2rgb8_X_c;
2312             break;
2313         case PIX_FMT_RGB4:
2314         case PIX_FMT_BGR4:
2315             *yuv2packed1 = yuv2rgb4_1_c;
2316             *yuv2packed2 = yuv2rgb4_2_c;
2317             *yuv2packedX = yuv2rgb4_X_c;
2318             break;
2319         case PIX_FMT_RGB4_BYTE:
2320         case PIX_FMT_BGR4_BYTE:
2321             *yuv2packed1 = yuv2rgb4b_1_c;
2322             *yuv2packed2 = yuv2rgb4b_2_c;
2323             *yuv2packedX = yuv2rgb4b_X_c;
2324             break;
2325         }
2326     }
2327 }
2328
2329 #define DEBUG_SWSCALE_BUFFERS 0
2330 #define DEBUG_BUFFERS(...) if (DEBUG_SWSCALE_BUFFERS) av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
2331
2332 static int swScale(SwsContext *c, const uint8_t* src[],
2333                    int srcStride[], int srcSliceY,
2334                    int srcSliceH, uint8_t* dst[], int dstStride[])
2335 {
2336     /* load a few things into local vars to make the code more readable? and faster */
2337     const int srcW= c->srcW;
2338     const int dstW= c->dstW;
2339     const int dstH= c->dstH;
2340     const int chrDstW= c->chrDstW;
2341     const int chrSrcW= c->chrSrcW;
2342     const int lumXInc= c->lumXInc;
2343     const int chrXInc= c->chrXInc;
2344     const enum PixelFormat dstFormat= c->dstFormat;
2345     const int flags= c->flags;
2346     int16_t *vLumFilterPos= c->vLumFilterPos;
2347     int16_t *vChrFilterPos= c->vChrFilterPos;
2348     int16_t *hLumFilterPos= c->hLumFilterPos;
2349     int16_t *hChrFilterPos= c->hChrFilterPos;
2350     int16_t *vLumFilter= c->vLumFilter;
2351     int16_t *vChrFilter= c->vChrFilter;
2352     int16_t *hLumFilter= c->hLumFilter;
2353     int16_t *hChrFilter= c->hChrFilter;
2354     int32_t *lumMmxFilter= c->lumMmxFilter;
2355     int32_t *chrMmxFilter= c->chrMmxFilter;
2356     int32_t av_unused *alpMmxFilter= c->alpMmxFilter;
2357     const int vLumFilterSize= c->vLumFilterSize;
2358     const int vChrFilterSize= c->vChrFilterSize;
2359     const int hLumFilterSize= c->hLumFilterSize;
2360     const int hChrFilterSize= c->hChrFilterSize;
2361     int16_t **lumPixBuf= c->lumPixBuf;
2362     int16_t **chrUPixBuf= c->chrUPixBuf;
2363     int16_t **chrVPixBuf= c->chrVPixBuf;
2364     int16_t **alpPixBuf= c->alpPixBuf;
2365     const int vLumBufSize= c->vLumBufSize;
2366     const int vChrBufSize= c->vChrBufSize;
2367     uint8_t *formatConvBuffer= c->formatConvBuffer;
2368     const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;
2369     const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);
2370     int lastDstY;
2371     uint32_t *pal=c->pal_yuv;
2372     int should_dither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat);
2373     yuv2planar1_fn yuv2yuv1 = c->yuv2yuv1;
2374     yuv2planarX_fn yuv2yuvX = c->yuv2yuvX;
2375     yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
2376     yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
2377     yuv2packedX_fn yuv2packedX = c->yuv2packedX;
2378
2379     /* vars which will change and which we need to store back in the context */
2380     int dstY= c->dstY;
2381     int lumBufIndex= c->lumBufIndex;
2382     int chrBufIndex= c->chrBufIndex;
2383     int lastInLumBuf= c->lastInLumBuf;
2384     int lastInChrBuf= c->lastInChrBuf;
2385
2386     if (isPacked(c->srcFormat)) {
2387         src[0]=
2388         src[1]=
2389         src[2]=
2390         src[3]= src[0];
2391         srcStride[0]=
2392         srcStride[1]=
2393         srcStride[2]=
2394         srcStride[3]= srcStride[0];
2395     }
2396     srcStride[1]<<= c->vChrDrop;
2397     srcStride[2]<<= c->vChrDrop;
2398
2399     DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
2400                   src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],
2401                   dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);
2402     DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
2403                    srcSliceY,    srcSliceH,    dstY,    dstH);
2404     DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
2405                    vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);
2406
2407     if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {
2408         static int warnedAlready=0; //FIXME move this into the context perhaps
2409         if (flags & SWS_PRINT_INFO && !warnedAlready) {
2410             av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"
2411                    "         ->cannot do aligned memory accesses anymore\n");
2412             warnedAlready=1;
2413         }
2414     }
2415
2416     /* Note the user might start scaling the picture in the middle so this
2417        will not get executed. This is not really intended but works
2418        currently, so people might do it. */
2419     if (srcSliceY ==0) {
2420         lumBufIndex=-1;
2421         chrBufIndex=-1;
2422         dstY=0;
2423         lastInLumBuf= -1;
2424         lastInChrBuf= -1;
2425     }
2426
2427     lastDstY= dstY;
2428
2429     for (;dstY < dstH; dstY++) {
2430         const int chrDstY= dstY>>c->chrDstVSubSample;
2431         uint8_t *dest[4] = {
2432             dst[0] + dstStride[0] * dstY,
2433             dst[1] + dstStride[1] * chrDstY,
2434             dst[2] + dstStride[2] * chrDstY,
2435             (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL,
2436         };
2437         const uint8_t *lumDither= should_dither ? dithers[7][dstY   &7] : flat64;
2438         const uint8_t *chrDither= should_dither ? dithers[7][chrDstY&7] : flat64;
2439
2440         const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input
2441         const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];
2442         const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input
2443         int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input
2444         int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input
2445         int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input
2446         int enough_lines;
2447
2448         //handle holes (FAST_BILINEAR & weird filters)
2449         if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;
2450         if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;
2451         assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
2452         assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
2453
2454         DEBUG_BUFFERS("dstY: %d\n", dstY);
2455         DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
2456                          firstLumSrcY,    lastLumSrcY,    lastInLumBuf);
2457         DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
2458                          firstChrSrcY,    lastChrSrcY,    lastInChrBuf);
2459
2460         // Do we have enough lines in this slice to output the dstY line
2461         enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);
2462
2463         if (!enough_lines) {
2464             lastLumSrcY = srcSliceY + srcSliceH - 1;
2465             lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
2466             DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
2467                                             lastLumSrcY, lastChrSrcY);
2468         }
2469
2470         //Do horizontal scaling
2471         while(lastInLumBuf < lastLumSrcY) {
2472             const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];
2473             const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];
2474             lumBufIndex++;
2475             assert(lumBufIndex < 2*vLumBufSize);
2476             assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);
2477             assert(lastInLumBuf + 1 - srcSliceY >= 0);
2478             hyscale(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,
2479                     hLumFilter, hLumFilterPos, hLumFilterSize,
2480                     formatConvBuffer,
2481                     pal, 0);
2482             if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
2483                 hyscale(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW,
2484                         lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
2485                         formatConvBuffer,
2486                         pal, 1);
2487             lastInLumBuf++;
2488             DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
2489                                lumBufIndex,    lastInLumBuf);
2490         }
2491         while(lastInChrBuf < lastChrSrcY) {
2492             const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];
2493             const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];
2494             chrBufIndex++;
2495             assert(chrBufIndex < 2*vChrBufSize);
2496             assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
2497             assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);
2498             //FIXME replace parameters through context struct (some at least)
2499
2500             if (c->needs_hcscale)
2501                 hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
2502                           chrDstW, src1, src2, chrSrcW, chrXInc,
2503                           hChrFilter, hChrFilterPos, hChrFilterSize,
2504                           formatConvBuffer, pal);
2505             lastInChrBuf++;
2506             DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
2507                                chrBufIndex,    lastInChrBuf);
2508         }
2509         //wrap buf index around to stay inside the ring buffer
2510         if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;
2511         if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;
2512         if (!enough_lines)
2513             break; //we can't output a dstY line so let's try with the next slice
2514
2515 #if HAVE_MMX
2516         updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf);
2517 #endif
2518         if (dstY >= dstH-2) {
2519             // hmm looks like we can't use MMX here without overwriting this array's tail
2520             find_c_packed_planar_out_funcs(c, &yuv2yuv1, &yuv2yuvX,
2521                                            &yuv2packed1, &yuv2packed2,
2522                                            &yuv2packedX);
2523         }
2524
2525         {
2526             const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
2527             const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
2528             const int16_t **chrVSrcPtr= (const int16_t **) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
2529             const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
2530
2531             if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like
2532                 const int chrSkipMask= (1<<c->chrDstVSubSample)-1;
2533                 if ((dstY&chrSkipMask) || isGray(dstFormat))
2534                     dest[1] = dest[2] = NULL; //FIXME split functions in lumi / chromi
2535                 if (c->yuv2yuv1 && vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12
2536                     const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;
2537                     yuv2yuv1(c, lumSrcPtr[0], chrUSrcPtr[0], chrVSrcPtr[0], alpBuf,
2538                              dest, dstW, chrDstW, lumDither, chrDither);
2539                 } else { //General YV12
2540                     yuv2yuvX(c, vLumFilter + dstY * vLumFilterSize,
2541                              lumSrcPtr, vLumFilterSize,
2542                              vChrFilter + chrDstY * vChrFilterSize,
2543                              chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
2544                              alpSrcPtr, dest, dstW, chrDstW, lumDither, chrDither);
2545                 }
2546             } else {
2547                 assert(lumSrcPtr  + vLumFilterSize - 1 < lumPixBuf  + vLumBufSize*2);
2548                 assert(chrUSrcPtr + vChrFilterSize - 1 < chrUPixBuf + vChrBufSize*2);
2549                 if (c->yuv2packed1 && vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB
2550                     int chrAlpha = vChrFilter[2 * dstY + 1];
2551                     yuv2packed1(c, *lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
2552                                 alpPixBuf ? *alpSrcPtr : NULL,
2553                                 dest[0], dstW, chrAlpha, dstY);
2554                 } else if (c->yuv2packed2 && vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB
2555                     int lumAlpha = vLumFilter[2 * dstY + 1];
2556                     int chrAlpha = vChrFilter[2 * dstY + 1];
2557                     lumMmxFilter[2] =
2558                     lumMmxFilter[3] = vLumFilter[2 * dstY   ] * 0x10001;
2559                     chrMmxFilter[2] =
2560                     chrMmxFilter[3] = vChrFilter[2 * chrDstY] * 0x10001;
2561                     yuv2packed2(c, lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
2562                                 alpPixBuf ? alpSrcPtr : NULL,
2563                                 dest[0], dstW, lumAlpha, chrAlpha, dstY);
2564                 } else { //general RGB
2565                     yuv2packedX(c, vLumFilter + dstY * vLumFilterSize,
2566                                 lumSrcPtr, vLumFilterSize,
2567                                 vChrFilter + dstY * vChrFilterSize,
2568                                 chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
2569                                 alpSrcPtr, dest[0], dstW, dstY);
2570                 }
2571             }
2572         }
2573     }
2574
2575     if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)
2576         fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);
2577
2578 #if HAVE_MMX2
2579     if (av_get_cpu_flags() & AV_CPU_FLAG_MMX2)
2580         __asm__ volatile("sfence":::"memory");
2581 #endif
2582     emms_c();
2583
2584     /* store changed local vars back in the context */
2585     c->dstY= dstY;
2586     c->lumBufIndex= lumBufIndex;
2587     c->chrBufIndex= chrBufIndex;
2588     c->lastInLumBuf= lastInLumBuf;
2589     c->lastInChrBuf= lastInChrBuf;
2590
2591     return dstY - lastDstY;
2592 }
2593
2594 static av_cold void sws_init_swScale_c(SwsContext *c)
2595 {
2596     enum PixelFormat srcFormat = c->srcFormat;
2597
2598     find_c_packed_planar_out_funcs(c, &c->yuv2yuv1, &c->yuv2yuvX,
2599                                    &c->yuv2packed1, &c->yuv2packed2,
2600                                    &c->yuv2packedX);
2601
2602     c->hScale       = hScale_c;
2603
2604     if (c->flags & SWS_FAST_BILINEAR) {
2605         c->hyscale_fast = hyscale_fast_c;
2606         c->hcscale_fast = hcscale_fast_c;
2607     }
2608
2609     c->chrToYV12 = NULL;
2610     switch(srcFormat) {
2611         case PIX_FMT_YUYV422  : c->chrToYV12 = yuy2ToUV_c; break;
2612         case PIX_FMT_UYVY422  : c->chrToYV12 = uyvyToUV_c; break;
2613         case PIX_FMT_NV12     : c->chrToYV12 = nv12ToUV_c; break;
2614         case PIX_FMT_NV21     : c->chrToYV12 = nv21ToUV_c; break;
2615         case PIX_FMT_RGB8     :
2616         case PIX_FMT_BGR8     :
2617         case PIX_FMT_PAL8     :
2618         case PIX_FMT_BGR4_BYTE:
2619         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV_c; break;
2620         case PIX_FMT_GRAY16BE :
2621         case PIX_FMT_YUV444P9BE:
2622         case PIX_FMT_YUV420P9BE:
2623         case PIX_FMT_YUV444P10BE:
2624         case PIX_FMT_YUV422P10BE:
2625         case PIX_FMT_YUV420P10BE:
2626         case PIX_FMT_YUV420P16BE:
2627         case PIX_FMT_YUV422P16BE:
2628         case PIX_FMT_YUV444P16BE: c->hScale16= HAVE_BIGENDIAN ? hScale16_c : hScale16X_c; break;
2629         case PIX_FMT_GRAY16LE :
2630         case PIX_FMT_YUV444P9LE:
2631         case PIX_FMT_YUV420P9LE:
2632         case PIX_FMT_YUV422P10LE:
2633         case PIX_FMT_YUV420P10LE:
2634         case PIX_FMT_YUV444P10LE:
2635         case PIX_FMT_YUV420P16LE:
2636         case PIX_FMT_YUV422P16LE:
2637         case PIX_FMT_YUV444P16LE: c->hScale16= HAVE_BIGENDIAN ? hScale16X_c : hScale16_c; break;
2638     }
2639     if (c->chrSrcHSubSample) {
2640         switch(srcFormat) {
2641         case PIX_FMT_RGB48BE : c->chrToYV12 = rgb48BEToUV_half_c; break;
2642         case PIX_FMT_RGB48LE : c->chrToYV12 = rgb48LEToUV_half_c; break;
2643         case PIX_FMT_BGR48BE : c->chrToYV12 = bgr48BEToUV_half_c; break;
2644         case PIX_FMT_BGR48LE : c->chrToYV12 = bgr48LEToUV_half_c; break;
2645         case PIX_FMT_RGB32   : c->chrToYV12 = bgr32ToUV_half_c;   break;
2646         case PIX_FMT_RGB32_1 : c->chrToYV12 = bgr321ToUV_half_c;  break;
2647         case PIX_FMT_BGR24   : c->chrToYV12 = bgr24ToUV_half_c;   break;
2648         case PIX_FMT_BGR565LE: c->chrToYV12 = bgr16leToUV_half_c; break;
2649         case PIX_FMT_BGR565BE: c->chrToYV12 = bgr16beToUV_half_c; break;
2650         case PIX_FMT_BGR555LE: c->chrToYV12 = bgr15leToUV_half_c; break;
2651         case PIX_FMT_BGR555BE: c->chrToYV12 = bgr15beToUV_half_c; break;
2652         case PIX_FMT_BGR32   : c->chrToYV12 = rgb32ToUV_half_c;   break;
2653         case PIX_FMT_BGR32_1 : c->chrToYV12 = rgb321ToUV_half_c;  break;
2654         case PIX_FMT_RGB24   : c->chrToYV12 = rgb24ToUV_half_c;   break;
2655         case PIX_FMT_RGB565LE: c->chrToYV12 = rgb16leToUV_half_c; break;
2656         case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_half_c; break;
2657         case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_half_c; break;
2658         case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_half_c; break;
2659         }
2660     } else {
2661         switch(srcFormat) {
2662         case PIX_FMT_RGB48BE : c->chrToYV12 = rgb48BEToUV_c; break;
2663         case PIX_FMT_RGB48LE : c->chrToYV12 = rgb48LEToUV_c; break;
2664         case PIX_FMT_BGR48BE : c->chrToYV12 = bgr48BEToUV_c; break;
2665         case PIX_FMT_BGR48LE : c->chrToYV12 = bgr48LEToUV_c; break;
2666         case PIX_FMT_RGB32   : c->chrToYV12 = bgr32ToUV_c;   break;
2667         case PIX_FMT_RGB32_1 : c->chrToYV12 = bgr321ToUV_c;  break;
2668         case PIX_FMT_BGR24   : c->chrToYV12 = bgr24ToUV_c;   break;
2669         case PIX_FMT_BGR565LE: c->chrToYV12 = bgr16leToUV_c; break;
2670         case PIX_FMT_BGR565BE: c->chrToYV12 = bgr16beToUV_c; break;
2671         case PIX_FMT_BGR555LE: c->chrToYV12 = bgr15leToUV_c; break;
2672         case PIX_FMT_BGR555BE: c->chrToYV12 = bgr15beToUV_c; break;
2673         case PIX_FMT_BGR32   : c->chrToYV12 = rgb32ToUV_c;   break;
2674         case PIX_FMT_BGR32_1 : c->chrToYV12 = rgb321ToUV_c;  break;
2675         case PIX_FMT_RGB24   : c->chrToYV12 = rgb24ToUV_c;   break;
2676         case PIX_FMT_RGB565LE: c->chrToYV12 = rgb16leToUV_c; break;
2677         case PIX_FMT_RGB565BE: c->chrToYV12 = rgb16beToUV_c; break;
2678         case PIX_FMT_RGB555LE: c->chrToYV12 = rgb15leToUV_c; break;
2679         case PIX_FMT_RGB555BE: c->chrToYV12 = rgb15beToUV_c; break;
2680         }
2681     }
2682
2683     c->lumToYV12 = NULL;
2684     c->alpToYV12 = NULL;
2685     switch (srcFormat) {
2686     case PIX_FMT_YUYV422  :
2687     case PIX_FMT_GRAY8A   :
2688                             c->lumToYV12 = yuy2ToY_c; break;
2689     case PIX_FMT_UYVY422  :
2690                             c->lumToYV12 = uyvyToY_c;    break;
2691     case PIX_FMT_BGR24    : c->lumToYV12 = bgr24ToY_c;   break;
2692     case PIX_FMT_BGR565LE : c->lumToYV12 = bgr16leToY_c; break;
2693     case PIX_FMT_BGR565BE : c->lumToYV12 = bgr16beToY_c; break;
2694     case PIX_FMT_BGR555LE : c->lumToYV12 = bgr15leToY_c; break;
2695     case PIX_FMT_BGR555BE : c->lumToYV12 = bgr15beToY_c; break;
2696     case PIX_FMT_RGB24    : c->lumToYV12 = rgb24ToY_c;   break;
2697     case PIX_FMT_RGB565LE : c->lumToYV12 = rgb16leToY_c; break;
2698     case PIX_FMT_RGB565BE : c->lumToYV12 = rgb16beToY_c; break;
2699     case PIX_FMT_RGB555LE : c->lumToYV12 = rgb15leToY_c; break;
2700     case PIX_FMT_RGB555BE : c->lumToYV12 = rgb15beToY_c; break;
2701     case PIX_FMT_RGB8     :
2702     case PIX_FMT_BGR8     :
2703     case PIX_FMT_PAL8     :
2704     case PIX_FMT_BGR4_BYTE:
2705     case PIX_FMT_RGB4_BYTE: c->lumToYV12 = palToY_c; break;
2706     case PIX_FMT_MONOBLACK: c->lumToYV12 = monoblack2Y_c; break;
2707     case PIX_FMT_MONOWHITE: c->lumToYV12 = monowhite2Y_c; break;
2708     case PIX_FMT_RGB32  : c->lumToYV12 = bgr32ToY_c;  break;
2709     case PIX_FMT_RGB32_1: c->lumToYV12 = bgr321ToY_c; break;
2710     case PIX_FMT_BGR32  : c->lumToYV12 = rgb32ToY_c;  break;
2711     case PIX_FMT_BGR32_1: c->lumToYV12 = rgb321ToY_c; break;
2712     case PIX_FMT_RGB48BE: c->lumToYV12 = rgb48BEToY_c; break;
2713     case PIX_FMT_RGB48LE: c->lumToYV12 = rgb48LEToY_c; break;
2714     case PIX_FMT_BGR48BE: c->lumToYV12 = bgr48BEToY_c; break;
2715     case PIX_FMT_BGR48LE: c->lumToYV12 = bgr48LEToY_c; break;
2716     }
2717     if (c->alpPixBuf) {
2718         switch (srcFormat) {
2719         case PIX_FMT_BGRA:
2720         case PIX_FMT_RGBA:  c->alpToYV12 = rgbaToA_c; break;
2721         case PIX_FMT_ABGR:
2722         case PIX_FMT_ARGB:  c->alpToYV12 = abgrToA_c; break;
2723         case PIX_FMT_Y400A: c->alpToYV12 = uyvyToY_c; break;
2724         case PIX_FMT_PAL8 : c->alpToYV12 = palToA_c; break;
2725         }
2726     }
2727
2728     if(isAnyRGB(c->srcFormat) || c->srcFormat == PIX_FMT_PAL8)
2729         c->hScale16= hScale16_c;
2730
2731     if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
2732         if (c->srcRange) {
2733             c->lumConvertRange = lumRangeFromJpeg_c;
2734             c->chrConvertRange = chrRangeFromJpeg_c;
2735         } else {
2736             c->lumConvertRange = lumRangeToJpeg_c;
2737             c->chrConvertRange = chrRangeToJpeg_c;
2738         }
2739     }
2740
2741     if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
2742           srcFormat == PIX_FMT_MONOBLACK || srcFormat == PIX_FMT_MONOWHITE))
2743         c->needs_hcscale = 1;
2744 }
2745
2746 SwsFunc ff_getSwsFunc(SwsContext *c)
2747 {
2748     sws_init_swScale_c(c);
2749
2750     if (HAVE_MMX)
2751         ff_sws_init_swScale_mmx(c);
2752     if (HAVE_ALTIVEC)
2753         ff_sws_init_swScale_altivec(c);
2754
2755     return swScale;
2756 }