]> git.sesse.net Git - ffmpeg/blob - libswscale/swscale_unscaled.c
Merge commit 'e791b915c774408fbc0ec9e7270b021899e08ccc'
[ffmpeg] / libswscale / swscale_unscaled.c
1 /*
2  * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <inttypes.h>
22 #include <string.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include "config.h"
26 #include "swscale.h"
27 #include "swscale_internal.h"
28 #include "rgb2rgb.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/cpu.h"
31 #include "libavutil/avutil.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/bswap.h"
34 #include "libavutil/pixdesc.h"
35 #include "libavutil/avassert.h"
36 #include "libavutil/avconfig.h"
37
38 DECLARE_ALIGNED(8, static const uint8_t, dithers)[8][8][8]={
39 {
40   {   0,  1,  0,  1,  0,  1,  0,  1,},
41   {   1,  0,  1,  0,  1,  0,  1,  0,},
42   {   0,  1,  0,  1,  0,  1,  0,  1,},
43   {   1,  0,  1,  0,  1,  0,  1,  0,},
44   {   0,  1,  0,  1,  0,  1,  0,  1,},
45   {   1,  0,  1,  0,  1,  0,  1,  0,},
46   {   0,  1,  0,  1,  0,  1,  0,  1,},
47   {   1,  0,  1,  0,  1,  0,  1,  0,},
48 },{
49   {   1,  2,  1,  2,  1,  2,  1,  2,},
50   {   3,  0,  3,  0,  3,  0,  3,  0,},
51   {   1,  2,  1,  2,  1,  2,  1,  2,},
52   {   3,  0,  3,  0,  3,  0,  3,  0,},
53   {   1,  2,  1,  2,  1,  2,  1,  2,},
54   {   3,  0,  3,  0,  3,  0,  3,  0,},
55   {   1,  2,  1,  2,  1,  2,  1,  2,},
56   {   3,  0,  3,  0,  3,  0,  3,  0,},
57 },{
58   {   2,  4,  3,  5,  2,  4,  3,  5,},
59   {   6,  0,  7,  1,  6,  0,  7,  1,},
60   {   3,  5,  2,  4,  3,  5,  2,  4,},
61   {   7,  1,  6,  0,  7,  1,  6,  0,},
62   {   2,  4,  3,  5,  2,  4,  3,  5,},
63   {   6,  0,  7,  1,  6,  0,  7,  1,},
64   {   3,  5,  2,  4,  3,  5,  2,  4,},
65   {   7,  1,  6,  0,  7,  1,  6,  0,},
66 },{
67   {   4,  8,  7, 11,  4,  8,  7, 11,},
68   {  12,  0, 15,  3, 12,  0, 15,  3,},
69   {   6, 10,  5,  9,  6, 10,  5,  9,},
70   {  14,  2, 13,  1, 14,  2, 13,  1,},
71   {   4,  8,  7, 11,  4,  8,  7, 11,},
72   {  12,  0, 15,  3, 12,  0, 15,  3,},
73   {   6, 10,  5,  9,  6, 10,  5,  9,},
74   {  14,  2, 13,  1, 14,  2, 13,  1,},
75 },{
76   {   9, 17, 15, 23,  8, 16, 14, 22,},
77   {  25,  1, 31,  7, 24,  0, 30,  6,},
78   {  13, 21, 11, 19, 12, 20, 10, 18,},
79   {  29,  5, 27,  3, 28,  4, 26,  2,},
80   {   8, 16, 14, 22,  9, 17, 15, 23,},
81   {  24,  0, 30,  6, 25,  1, 31,  7,},
82   {  12, 20, 10, 18, 13, 21, 11, 19,},
83   {  28,  4, 26,  2, 29,  5, 27,  3,},
84 },{
85   {  18, 34, 30, 46, 17, 33, 29, 45,},
86   {  50,  2, 62, 14, 49,  1, 61, 13,},
87   {  26, 42, 22, 38, 25, 41, 21, 37,},
88   {  58, 10, 54,  6, 57,  9, 53,  5,},
89   {  16, 32, 28, 44, 19, 35, 31, 47,},
90   {  48,  0, 60, 12, 51,  3, 63, 15,},
91   {  24, 40, 20, 36, 27, 43, 23, 39,},
92   {  56,  8, 52,  4, 59, 11, 55,  7,},
93 },{
94   {  18, 34, 30, 46, 17, 33, 29, 45,},
95   {  50,  2, 62, 14, 49,  1, 61, 13,},
96   {  26, 42, 22, 38, 25, 41, 21, 37,},
97   {  58, 10, 54,  6, 57,  9, 53,  5,},
98   {  16, 32, 28, 44, 19, 35, 31, 47,},
99   {  48,  0, 60, 12, 51,  3, 63, 15,},
100   {  24, 40, 20, 36, 27, 43, 23, 39,},
101   {  56,  8, 52,  4, 59, 11, 55,  7,},
102 },{
103   {  36, 68, 60, 92, 34, 66, 58, 90,},
104   { 100,  4,124, 28, 98,  2,122, 26,},
105   {  52, 84, 44, 76, 50, 82, 42, 74,},
106   { 116, 20,108, 12,114, 18,106, 10,},
107   {  32, 64, 56, 88, 38, 70, 62, 94,},
108   {  96,  0,120, 24,102,  6,126, 30,},
109   {  48, 80, 40, 72, 54, 86, 46, 78,},
110   { 112, 16,104,  8,118, 22,110, 14,},
111 }};
112
113 static const uint16_t dither_scale[15][16]={
114 {    2,    3,    3,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,    5,},
115 {    2,    3,    7,    7,   13,   13,   25,   25,   25,   25,   25,   25,   25,   25,   25,   25,},
116 {    3,    3,    4,   15,   15,   29,   57,   57,   57,  113,  113,  113,  113,  113,  113,  113,},
117 {    3,    4,    4,    5,   31,   31,   61,  121,  241,  241,  241,  241,  481,  481,  481,  481,},
118 {    3,    4,    5,    5,    6,   63,   63,  125,  249,  497,  993,  993,  993,  993,  993, 1985,},
119 {    3,    5,    6,    6,    6,    7,  127,  127,  253,  505, 1009, 2017, 4033, 4033, 4033, 4033,},
120 {    3,    5,    6,    7,    7,    7,    8,  255,  255,  509, 1017, 2033, 4065, 8129,16257,16257,},
121 {    3,    5,    6,    8,    8,    8,    8,    9,  511,  511, 1021, 2041, 4081, 8161,16321,32641,},
122 {    3,    5,    7,    8,    9,    9,    9,    9,   10, 1023, 1023, 2045, 4089, 8177,16353,32705,},
123 {    3,    5,    7,    8,   10,   10,   10,   10,   10,   11, 2047, 2047, 4093, 8185,16369,32737,},
124 {    3,    5,    7,    8,   10,   11,   11,   11,   11,   11,   12, 4095, 4095, 8189,16377,32753,},
125 {    3,    5,    7,    9,   10,   12,   12,   12,   12,   12,   12,   13, 8191, 8191,16381,32761,},
126 {    3,    5,    7,    9,   10,   12,   13,   13,   13,   13,   13,   13,   14,16383,16383,32765,},
127 {    3,    5,    7,    9,   10,   12,   14,   14,   14,   14,   14,   14,   14,   15,32767,32767,},
128 {    3,    5,    7,    9,   11,   12,   14,   15,   15,   15,   15,   15,   15,   15,   16,65535,},
129 };
130
131
132 static void fillPlane(uint8_t *plane, int stride, int width, int height, int y,
133                       uint8_t val)
134 {
135     int i;
136     uint8_t *ptr = plane + stride * y;
137     for (i = 0; i < height; i++) {
138         memset(ptr, val, width);
139         ptr += stride;
140     }
141 }
142
143 static void copyPlane(const uint8_t *src, int srcStride,
144                       int srcSliceY, int srcSliceH, int width,
145                       uint8_t *dst, int dstStride)
146 {
147     dst += dstStride * srcSliceY;
148     if (dstStride == srcStride && srcStride > 0) {
149         memcpy(dst, src, srcSliceH * dstStride);
150     } else {
151         int i;
152         for (i = 0; i < srcSliceH; i++) {
153             memcpy(dst, src, width);
154             src += srcStride;
155             dst += dstStride;
156         }
157     }
158 }
159
160 static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[],
161                                int srcStride[], int srcSliceY,
162                                int srcSliceH, uint8_t *dstParam[],
163                                int dstStride[])
164 {
165     uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
166
167     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
168               dstParam[0], dstStride[0]);
169
170     if (c->dstFormat == AV_PIX_FMT_NV12)
171         interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2,
172                         srcStride[1], srcStride[2], dstStride[1]);
173     else
174         interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2,
175                         srcStride[2], srcStride[1], dstStride[1]);
176
177     return srcSliceH;
178 }
179
180 static int nv12ToPlanarWrapper(SwsContext *c, const uint8_t *src[],
181                                int srcStride[], int srcSliceY,
182                                int srcSliceH, uint8_t *dstParam[],
183                                int dstStride[])
184 {
185     uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2;
186     uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2;
187
188     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
189               dstParam[0], dstStride[0]);
190
191     if (c->srcFormat == AV_PIX_FMT_NV12)
192         deinterleaveBytes(src[1], dst1, dst2,c->srcW / 2, srcSliceH / 2,
193                           srcStride[1], dstStride[1], dstStride[2]);
194     else
195         deinterleaveBytes(src[1], dst2, dst1, c->srcW / 2, srcSliceH / 2,
196                           srcStride[1], dstStride[2], dstStride[1]);
197
198     return srcSliceH;
199 }
200
201 static int planarToP010Wrapper(SwsContext *c, const uint8_t *src8[],
202                                int srcStride[], int srcSliceY,
203                                int srcSliceH, uint8_t *dstParam8[],
204                                int dstStride[])
205 {
206     const uint16_t **src = (const uint16_t**)src8;
207     uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY);
208     uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2);
209     int x, y;
210
211     av_assert0(!(srcStride[0] % 2 || srcStride[1] % 2 || srcStride[2] % 2 ||
212                  dstStride[0] % 2 || dstStride[1] % 2));
213
214     for (y = 0; y < srcSliceH; y++) {
215         uint16_t *tdstY = dstY;
216         const uint16_t *tsrc0 = src[0];
217         for (x = c->srcW; x > 0; x--) {
218             *tdstY++ = *tsrc0++ << 6;
219         }
220         src[0] += srcStride[0] / 2;
221         dstY += dstStride[0] / 2;
222
223         if (!(y & 1)) {
224             uint16_t *tdstUV = dstUV;
225             const uint16_t *tsrc1 = src[1];
226             const uint16_t *tsrc2 = src[2];
227             for (x = c->srcW / 2; x > 0; x--) {
228                 *tdstUV++ = *tsrc1++ << 6;
229                 *tdstUV++ = *tsrc2++ << 6;
230             }
231             src[1] += srcStride[1] / 2;
232             src[2] += srcStride[2] / 2;
233             dstUV += dstStride[1] / 2;
234         }
235     }
236
237     return srcSliceH;
238 }
239
240 #if AV_HAVE_BIGENDIAN
241 #define output_pixel(p, v) do { \
242         uint16_t *pp = (p); \
243         AV_WL16(pp, (v)); \
244     } while(0)
245 #else
246 #define output_pixel(p, v) (*p) = (v)
247 #endif
248
249 static int planar8ToP01xleWrapper(SwsContext *c, const uint8_t *src[],
250                                   int srcStride[], int srcSliceY,
251                                   int srcSliceH, uint8_t *dstParam8[],
252                                   int dstStride[])
253 {
254     uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY);
255     uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2);
256     int x, y, t;
257
258     av_assert0(!(dstStride[0] % 2 || dstStride[1] % 2));
259
260     for (y = 0; y < srcSliceH; y++) {
261         uint16_t *tdstY = dstY;
262         const uint8_t *tsrc0 = src[0];
263         for (x = c->srcW; x > 0; x--) {
264             t = *tsrc0++;
265             output_pixel(tdstY++, t | (t << 8));
266         }
267         src[0] += srcStride[0];
268         dstY += dstStride[0] / 2;
269
270         if (!(y & 1)) {
271             uint16_t *tdstUV = dstUV;
272             const uint8_t *tsrc1 = src[1];
273             const uint8_t *tsrc2 = src[2];
274             for (x = c->srcW / 2; x > 0; x--) {
275                 t = *tsrc1++;
276                 output_pixel(tdstUV++, t | (t << 8));
277                 t = *tsrc2++;
278                 output_pixel(tdstUV++, t | (t << 8));
279             }
280             src[1] += srcStride[1];
281             src[2] += srcStride[2];
282             dstUV += dstStride[1] / 2;
283         }
284     }
285
286     return srcSliceH;
287 }
288
289 #undef output_pixel
290
291 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
292                                int srcStride[], int srcSliceY, int srcSliceH,
293                                uint8_t *dstParam[], int dstStride[])
294 {
295     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
296
297     yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
298                srcStride[1], dstStride[0]);
299
300     return srcSliceH;
301 }
302
303 static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[],
304                                int srcStride[], int srcSliceY, int srcSliceH,
305                                uint8_t *dstParam[], int dstStride[])
306 {
307     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
308
309     yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
310                srcStride[1], dstStride[0]);
311
312     return srcSliceH;
313 }
314
315 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
316                                 int srcStride[], int srcSliceY, int srcSliceH,
317                                 uint8_t *dstParam[], int dstStride[])
318 {
319     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
320
321     yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
322                   srcStride[1], dstStride[0]);
323
324     return srcSliceH;
325 }
326
327 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[],
328                                 int srcStride[], int srcSliceY, int srcSliceH,
329                                 uint8_t *dstParam[], int dstStride[])
330 {
331     uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
332
333     yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
334                   srcStride[1], dstStride[0]);
335
336     return srcSliceH;
337 }
338
339 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
340                                int srcStride[], int srcSliceY, int srcSliceH,
341                                uint8_t *dstParam[], int dstStride[])
342 {
343     uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
344     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
345     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
346
347     yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
348                  dstStride[1], srcStride[0]);
349
350     if (dstParam[3])
351         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
352
353     return srcSliceH;
354 }
355
356 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
357                                int srcStride[], int srcSliceY, int srcSliceH,
358                                uint8_t *dstParam[], int dstStride[])
359 {
360     uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
361     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
362     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
363
364     yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
365                  dstStride[1], srcStride[0]);
366
367     return srcSliceH;
368 }
369
370 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
371                                int srcStride[], int srcSliceY, int srcSliceH,
372                                uint8_t *dstParam[], int dstStride[])
373 {
374     uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
375     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
376     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
377
378     uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
379                  dstStride[1], srcStride[0]);
380
381     if (dstParam[3])
382         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
383
384     return srcSliceH;
385 }
386
387 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
388                                int srcStride[], int srcSliceY, int srcSliceH,
389                                uint8_t *dstParam[], int dstStride[])
390 {
391     uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
392     uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
393     uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
394
395     uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
396                  dstStride[1], srcStride[0]);
397
398     return srcSliceH;
399 }
400
401 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels,
402                              const uint8_t *palette)
403 {
404     int i;
405     for (i = 0; i < num_pixels; i++)
406         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24);
407 }
408
409 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels,
410                                const uint8_t *palette)
411 {
412     int i;
413
414     for (i = 0; i < num_pixels; i++)
415         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1];
416 }
417
418 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
419                              const uint8_t *palette)
420 {
421     int i;
422
423     for (i = 0; i < num_pixels; i++) {
424         //FIXME slow?
425         dst[0] = palette[src[i << 1] * 4 + 0];
426         dst[1] = palette[src[i << 1] * 4 + 1];
427         dst[2] = palette[src[i << 1] * 4 + 2];
428         dst += 3;
429     }
430 }
431
432 static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[],
433                               int srcStride[], int srcSliceY, int srcSliceH,
434                               uint8_t *dst[], int dstStride[])
435 {
436     int i, j, p;
437
438     for (p = 0; p < 4; p++) {
439         int srcstr = srcStride[p] / 2;
440         int dststr = dstStride[p] / 2;
441         uint16_t       *dstPtr =       (uint16_t *) dst[p];
442         const uint16_t *srcPtr = (const uint16_t *) src[p];
443         int min_stride         = FFMIN(FFABS(srcstr), FFABS(dststr));
444         if(!dstPtr || !srcPtr)
445             continue;
446         dstPtr += (srcSliceY >> c->chrDstVSubSample) * dststr;
447         for (i = 0; i < (srcSliceH >> c->chrDstVSubSample); i++) {
448             for (j = 0; j < min_stride; j++) {
449                 dstPtr[j] = av_bswap16(srcPtr[j]);
450             }
451             srcPtr += srcstr;
452             dstPtr += dststr;
453         }
454     }
455
456     return srcSliceH;
457 }
458
459 static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
460                            int srcSliceY, int srcSliceH, uint8_t *dst[],
461                            int dstStride[])
462 {
463     const enum AVPixelFormat srcFormat = c->srcFormat;
464     const enum AVPixelFormat dstFormat = c->dstFormat;
465     void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
466                  const uint8_t *palette) = NULL;
467     int i;
468     uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
469     const uint8_t *srcPtr = src[0];
470
471     if (srcFormat == AV_PIX_FMT_YA8) {
472         switch (dstFormat) {
473         case AV_PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
474         case AV_PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
475         case AV_PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
476         case AV_PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
477         case AV_PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
478         case AV_PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
479         }
480     } else if (usePal(srcFormat)) {
481         switch (dstFormat) {
482         case AV_PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
483         case AV_PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
484         case AV_PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
485         case AV_PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
486         case AV_PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
487         case AV_PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
488         }
489     }
490
491     if (!conv)
492         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
493                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
494     else {
495         for (i = 0; i < srcSliceH; i++) {
496             conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
497             srcPtr += srcStride[0];
498             dstPtr += dstStride[0];
499         }
500     }
501
502     return srcSliceH;
503 }
504
505 static void packed16togbra16(const uint8_t *src, int srcStride,
506                              uint16_t *dst[], int dstStride[], int srcSliceH,
507                              int src_alpha, int swap, int shift, int width)
508 {
509     int x, h, i;
510     int dst_alpha = dst[3] != NULL;
511     for (h = 0; h < srcSliceH; h++) {
512         uint16_t *src_line = (uint16_t *)(src + srcStride * h);
513         switch (swap) {
514         case 3:
515             if (src_alpha && dst_alpha) {
516                 for (x = 0; x < width; x++) {
517                     dst[0][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
518                     dst[1][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
519                     dst[2][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
520                     dst[3][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
521                 }
522             } else if (dst_alpha) {
523                 for (x = 0; x < width; x++) {
524                     dst[0][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
525                     dst[1][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
526                     dst[2][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
527                     dst[3][x] = 0xFFFF;
528                 }
529             } else if (src_alpha) {
530                 for (x = 0; x < width; x++) {
531                     dst[0][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
532                     dst[1][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
533                     dst[2][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
534                     src_line++;
535                 }
536             } else {
537                 for (x = 0; x < width; x++) {
538                     dst[0][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
539                     dst[1][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
540                     dst[2][x] = av_bswap16(av_bswap16(*src_line++) >> shift);
541                 }
542             }
543             break;
544         case 2:
545             if (src_alpha && dst_alpha) {
546                 for (x = 0; x < width; x++) {
547                     dst[0][x] = av_bswap16(*src_line++ >> shift);
548                     dst[1][x] = av_bswap16(*src_line++ >> shift);
549                     dst[2][x] = av_bswap16(*src_line++ >> shift);
550                     dst[3][x] = av_bswap16(*src_line++ >> shift);
551                 }
552             } else if (dst_alpha) {
553                 for (x = 0; x < width; x++) {
554                     dst[0][x] = av_bswap16(*src_line++ >> shift);
555                     dst[1][x] = av_bswap16(*src_line++ >> shift);
556                     dst[2][x] = av_bswap16(*src_line++ >> shift);
557                     dst[3][x] = 0xFFFF;
558                 }
559             } else if (src_alpha) {
560                 for (x = 0; x < width; x++) {
561                     dst[0][x] = av_bswap16(*src_line++ >> shift);
562                     dst[1][x] = av_bswap16(*src_line++ >> shift);
563                     dst[2][x] = av_bswap16(*src_line++ >> shift);
564                     src_line++;
565                 }
566             } else {
567                 for (x = 0; x < width; x++) {
568                     dst[0][x] = av_bswap16(*src_line++ >> shift);
569                     dst[1][x] = av_bswap16(*src_line++ >> shift);
570                     dst[2][x] = av_bswap16(*src_line++ >> shift);
571                 }
572             }
573             break;
574         case 1:
575             if (src_alpha && dst_alpha) {
576                 for (x = 0; x < width; x++) {
577                     dst[0][x] = av_bswap16(*src_line++) >> shift;
578                     dst[1][x] = av_bswap16(*src_line++) >> shift;
579                     dst[2][x] = av_bswap16(*src_line++) >> shift;
580                     dst[3][x] = av_bswap16(*src_line++) >> shift;
581                 }
582             } else if (dst_alpha) {
583                 for (x = 0; x < width; x++) {
584                     dst[0][x] = av_bswap16(*src_line++) >> shift;
585                     dst[1][x] = av_bswap16(*src_line++) >> shift;
586                     dst[2][x] = av_bswap16(*src_line++) >> shift;
587                     dst[3][x] = 0xFFFF;
588                 }
589             } else if (src_alpha) {
590                 for (x = 0; x < width; x++) {
591                     dst[0][x] = av_bswap16(*src_line++) >> shift;
592                     dst[1][x] = av_bswap16(*src_line++) >> shift;
593                     dst[2][x] = av_bswap16(*src_line++) >> shift;
594                     src_line++;
595                 }
596             } else {
597                 for (x = 0; x < width; x++) {
598                     dst[0][x] = av_bswap16(*src_line++) >> shift;
599                     dst[1][x] = av_bswap16(*src_line++) >> shift;
600                     dst[2][x] = av_bswap16(*src_line++) >> shift;
601                 }
602             }
603             break;
604         default:
605             if (src_alpha && dst_alpha) {
606                 for (x = 0; x < width; x++) {
607                     dst[0][x] = *src_line++ >> shift;
608                     dst[1][x] = *src_line++ >> shift;
609                     dst[2][x] = *src_line++ >> shift;
610                     dst[3][x] = *src_line++ >> shift;
611                 }
612             } else if (dst_alpha) {
613                 for (x = 0; x < width; x++) {
614                     dst[0][x] = *src_line++ >> shift;
615                     dst[1][x] = *src_line++ >> shift;
616                     dst[2][x] = *src_line++ >> shift;
617                     dst[3][x] = 0xFFFF;
618                 }
619             } else if (src_alpha) {
620                 for (x = 0; x < width; x++) {
621                     dst[0][x] = *src_line++ >> shift;
622                     dst[1][x] = *src_line++ >> shift;
623                     dst[2][x] = *src_line++ >> shift;
624                     src_line++;
625                 }
626             } else {
627                 for (x = 0; x < width; x++) {
628                     dst[0][x] = *src_line++ >> shift;
629                     dst[1][x] = *src_line++ >> shift;
630                     dst[2][x] = *src_line++ >> shift;
631                 }
632             }
633         }
634         for (i = 0; i < 4; i++)
635             dst[i] += dstStride[i] >> 1;
636     }
637 }
638
639 static int Rgb16ToPlanarRgb16Wrapper(SwsContext *c, const uint8_t *src[],
640                                      int srcStride[], int srcSliceY, int srcSliceH,
641                                      uint8_t *dst[], int dstStride[])
642 {
643     uint16_t *dst2013[] = { (uint16_t *)dst[2], (uint16_t *)dst[0], (uint16_t *)dst[1], (uint16_t *)dst[3] };
644     uint16_t *dst1023[] = { (uint16_t *)dst[1], (uint16_t *)dst[0], (uint16_t *)dst[2], (uint16_t *)dst[3] };
645     int stride2013[] = { dstStride[2], dstStride[0], dstStride[1], dstStride[3] };
646     int stride1023[] = { dstStride[1], dstStride[0], dstStride[2], dstStride[3] };
647     const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat);
648     const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
649     int bpc = dst_format->comp[0].depth;
650     int alpha = src_format->flags & AV_PIX_FMT_FLAG_ALPHA;
651     int swap = 0;
652     int i;
653
654     if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) ||
655         !HAVE_BIGENDIAN &&   src_format->flags & AV_PIX_FMT_FLAG_BE)
656         swap++;
657     if ( HAVE_BIGENDIAN && !(dst_format->flags & AV_PIX_FMT_FLAG_BE) ||
658         !HAVE_BIGENDIAN &&   dst_format->flags & AV_PIX_FMT_FLAG_BE)
659         swap += 2;
660
661     if ((dst_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) !=
662         (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) || bpc < 9) {
663         av_log(c, AV_LOG_ERROR, "unsupported conversion to planar RGB %s -> %s\n",
664                src_format->name, dst_format->name);
665         return srcSliceH;
666     }
667
668     for(i=0; i<4; i++) {
669         dst2013[i] += stride2013[i] * srcSliceY / 2;
670         dst1023[i] += stride1023[i] * srcSliceY / 2;
671     }
672
673     switch (c->srcFormat) {
674     case AV_PIX_FMT_RGB48LE:
675     case AV_PIX_FMT_RGB48BE:
676     case AV_PIX_FMT_RGBA64LE:
677     case AV_PIX_FMT_RGBA64BE:
678         packed16togbra16(src[0], srcStride[0],
679                          dst2013, stride2013, srcSliceH, alpha, swap,
680                          16 - bpc, c->srcW);
681         break;
682     case AV_PIX_FMT_BGR48LE:
683     case AV_PIX_FMT_BGR48BE:
684     case AV_PIX_FMT_BGRA64LE:
685     case AV_PIX_FMT_BGRA64BE:
686         packed16togbra16(src[0], srcStride[0],
687                          dst1023, stride1023, srcSliceH, alpha, swap,
688                          16 - bpc, c->srcW);
689         break;
690     default:
691         av_log(c, AV_LOG_ERROR,
692                "unsupported conversion to planar RGB %s -> %s\n",
693                src_format->name, dst_format->name);
694     }
695
696     return srcSliceH;
697 }
698
699 static void gbr16ptopacked16(const uint16_t *src[], int srcStride[],
700                              uint8_t *dst, int dstStride, int srcSliceH,
701                              int alpha, int swap, int bpp, int width)
702 {
703     int x, h, i;
704     int src_alpha = src[3] != NULL;
705     int scale_high = 16 - bpp, scale_low = (bpp - 8) * 2;
706     for (h = 0; h < srcSliceH; h++) {
707         uint16_t *dest = (uint16_t *)(dst + dstStride * h);
708         uint16_t component;
709
710         switch(swap) {
711         case 3:
712             if (alpha && !src_alpha) {
713                 for (x = 0; x < width; x++) {
714                     component = av_bswap16(src[0][x]);
715                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
716                     component = av_bswap16(src[1][x]);
717                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
718                     component = av_bswap16(src[2][x]);
719                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
720                     *dest++ = 0xffff;
721                 }
722             } else if (alpha && src_alpha) {
723                 for (x = 0; x < width; x++) {
724                     component = av_bswap16(src[0][x]);
725                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
726                     component = av_bswap16(src[1][x]);
727                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
728                     component = av_bswap16(src[2][x]);
729                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
730                     component = av_bswap16(src[3][x]);
731                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
732                 }
733             } else {
734                 for (x = 0; x < width; x++) {
735                     component = av_bswap16(src[0][x]);
736                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
737                     component = av_bswap16(src[1][x]);
738                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
739                     component = av_bswap16(src[2][x]);
740                     *dest++ = av_bswap16(component << scale_high | component >> scale_low);
741                 }
742             }
743             break;
744         case 2:
745             if (alpha && !src_alpha) {
746                 for (x = 0; x < width; x++) {
747                     *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low);
748                     *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low);
749                     *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low);
750                     *dest++ = 0xffff;
751                 }
752             } else if (alpha && src_alpha) {
753                 for (x = 0; x < width; x++) {
754                     *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low);
755                     *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low);
756                     *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low);
757                     *dest++ = av_bswap16(src[3][x] << scale_high | src[3][x] >> scale_low);
758                 }
759             } else {
760                 for (x = 0; x < width; x++) {
761                     *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low);
762                     *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low);
763                     *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low);
764                 }
765             }
766             break;
767         case 1:
768             if (alpha && !src_alpha) {
769                 for (x = 0; x < width; x++) {
770                     *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low;
771                     *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low;
772                     *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low;
773                     *dest++ = 0xffff;
774                 }
775             } else if (alpha && src_alpha) {
776                 for (x = 0; x < width; x++) {
777                     *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low;
778                     *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low;
779                     *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low;
780                     *dest++ = av_bswap16(src[3][x]) << scale_high | av_bswap16(src[3][x]) >> scale_low;
781                 }
782             } else {
783                 for (x = 0; x < width; x++) {
784                     *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low;
785                     *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low;
786                     *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low;
787                 }
788             }
789             break;
790         default:
791             if (alpha && !src_alpha) {
792                 for (x = 0; x < width; x++) {
793                     *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low;
794                     *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low;
795                     *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low;
796                     *dest++ = 0xffff;
797                 }
798             } else if (alpha && src_alpha) {
799                 for (x = 0; x < width; x++) {
800                     *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low;
801                     *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low;
802                     *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low;
803                     *dest++ = src[3][x] << scale_high | src[3][x] >> scale_low;
804                 }
805             } else {
806                 for (x = 0; x < width; x++) {
807                     *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low;
808                     *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low;
809                     *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low;
810                 }
811             }
812         }
813         for (i = 0; i < 3 + src_alpha; i++)
814             src[i] += srcStride[i] >> 1;
815     }
816 }
817
818 static int planarRgb16ToRgb16Wrapper(SwsContext *c, const uint8_t *src[],
819                                      int srcStride[], int srcSliceY, int srcSliceH,
820                                      uint8_t *dst[], int dstStride[])
821 {
822     const uint16_t *src102[] = { (uint16_t *)src[1], (uint16_t *)src[0], (uint16_t *)src[2], (uint16_t *)src[3] };
823     const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1], (uint16_t *)src[3] };
824     int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] };
825     int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] };
826     const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat);
827     const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat);
828     int bits_per_sample = src_format->comp[0].depth;
829     int swap = 0;
830     if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) ||
831         !HAVE_BIGENDIAN &&   src_format->flags & AV_PIX_FMT_FLAG_BE)
832         swap++;
833     if ( HAVE_BIGENDIAN && !(dst_format->flags & AV_PIX_FMT_FLAG_BE) ||
834         !HAVE_BIGENDIAN &&   dst_format->flags & AV_PIX_FMT_FLAG_BE)
835         swap += 2;
836
837     if ((src_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) !=
838         (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) ||
839         bits_per_sample <= 8) {
840         av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
841                src_format->name, dst_format->name);
842         return srcSliceH;
843     }
844     switch (c->dstFormat) {
845     case AV_PIX_FMT_BGR48LE:
846     case AV_PIX_FMT_BGR48BE:
847         gbr16ptopacked16(src102, stride102,
848                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
849                          srcSliceH, 0, swap, bits_per_sample, c->srcW);
850         break;
851     case AV_PIX_FMT_RGB48LE:
852     case AV_PIX_FMT_RGB48BE:
853         gbr16ptopacked16(src201, stride201,
854                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
855                          srcSliceH, 0, swap, bits_per_sample, c->srcW);
856         break;
857     case AV_PIX_FMT_RGBA64LE:
858     case AV_PIX_FMT_RGBA64BE:
859          gbr16ptopacked16(src201, stride201,
860                           dst[0] + srcSliceY * dstStride[0], dstStride[0],
861                           srcSliceH, 1, swap, bits_per_sample, c->srcW);
862         break;
863     case AV_PIX_FMT_BGRA64LE:
864     case AV_PIX_FMT_BGRA64BE:
865         gbr16ptopacked16(src102, stride102,
866                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
867                          srcSliceH, 1, swap, bits_per_sample, c->srcW);
868         break;
869     default:
870         av_log(c, AV_LOG_ERROR,
871                "unsupported planar RGB conversion %s -> %s\n",
872                src_format->name, dst_format->name);
873     }
874
875     return srcSliceH;
876 }
877
878 static void gbr24ptopacked24(const uint8_t *src[], int srcStride[],
879                              uint8_t *dst, int dstStride, int srcSliceH,
880                              int width)
881 {
882     int x, h, i;
883     for (h = 0; h < srcSliceH; h++) {
884         uint8_t *dest = dst + dstStride * h;
885         for (x = 0; x < width; x++) {
886             *dest++ = src[0][x];
887             *dest++ = src[1][x];
888             *dest++ = src[2][x];
889         }
890
891         for (i = 0; i < 3; i++)
892             src[i] += srcStride[i];
893     }
894 }
895
896 static void gbr24ptopacked32(const uint8_t *src[], int srcStride[],
897                              uint8_t *dst, int dstStride, int srcSliceH,
898                              int alpha_first, int width)
899 {
900     int x, h, i;
901     for (h = 0; h < srcSliceH; h++) {
902         uint8_t *dest = dst + dstStride * h;
903
904         if (alpha_first) {
905             for (x = 0; x < width; x++) {
906                 *dest++ = 0xff;
907                 *dest++ = src[0][x];
908                 *dest++ = src[1][x];
909                 *dest++ = src[2][x];
910             }
911         } else {
912             for (x = 0; x < width; x++) {
913                 *dest++ = src[0][x];
914                 *dest++ = src[1][x];
915                 *dest++ = src[2][x];
916                 *dest++ = 0xff;
917             }
918         }
919
920         for (i = 0; i < 3; i++)
921             src[i] += srcStride[i];
922     }
923 }
924
925 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[],
926                                  int srcStride[], int srcSliceY, int srcSliceH,
927                                  uint8_t *dst[], int dstStride[])
928 {
929     int alpha_first = 0;
930     const uint8_t *src102[] = { src[1], src[0], src[2] };
931     const uint8_t *src201[] = { src[2], src[0], src[1] };
932     int stride102[] = { srcStride[1], srcStride[0], srcStride[2] };
933     int stride201[] = { srcStride[2], srcStride[0], srcStride[1] };
934
935     if (c->srcFormat != AV_PIX_FMT_GBRP) {
936         av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
937                av_get_pix_fmt_name(c->srcFormat),
938                av_get_pix_fmt_name(c->dstFormat));
939         return srcSliceH;
940     }
941
942     switch (c->dstFormat) {
943     case AV_PIX_FMT_BGR24:
944         gbr24ptopacked24(src102, stride102,
945                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
946                          srcSliceH, c->srcW);
947         break;
948
949     case AV_PIX_FMT_RGB24:
950         gbr24ptopacked24(src201, stride201,
951                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
952                          srcSliceH, c->srcW);
953         break;
954
955     case AV_PIX_FMT_ARGB:
956         alpha_first = 1;
957     case AV_PIX_FMT_RGBA:
958         gbr24ptopacked32(src201, stride201,
959                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
960                          srcSliceH, alpha_first, c->srcW);
961         break;
962
963     case AV_PIX_FMT_ABGR:
964         alpha_first = 1;
965     case AV_PIX_FMT_BGRA:
966         gbr24ptopacked32(src102, stride102,
967                          dst[0] + srcSliceY * dstStride[0], dstStride[0],
968                          srcSliceH, alpha_first, c->srcW);
969         break;
970
971     default:
972         av_log(c, AV_LOG_ERROR,
973                "unsupported planar RGB conversion %s -> %s\n",
974                av_get_pix_fmt_name(c->srcFormat),
975                av_get_pix_fmt_name(c->dstFormat));
976     }
977
978     return srcSliceH;
979 }
980
981 static int planarRgbToplanarRgbWrapper(SwsContext *c,
982                                        const uint8_t *src[], int srcStride[],
983                                        int srcSliceY, int srcSliceH,
984                                        uint8_t *dst[], int dstStride[])
985 {
986     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
987               dst[0], dstStride[0]);
988     copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW,
989               dst[1], dstStride[1]);
990     copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW,
991               dst[2], dstStride[2]);
992     if (dst[3])
993         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
994
995     return srcSliceH;
996 }
997
998 static void packedtogbr24p(const uint8_t *src, int srcStride,
999                            uint8_t *dst[], int dstStride[], int srcSliceH,
1000                            int alpha_first, int inc_size, int width)
1001 {
1002     uint8_t *dest[3];
1003     int x, h;
1004
1005     dest[0] = dst[0];
1006     dest[1] = dst[1];
1007     dest[2] = dst[2];
1008
1009     if (alpha_first)
1010         src++;
1011
1012     for (h = 0; h < srcSliceH; h++) {
1013         for (x = 0; x < width; x++) {
1014             dest[0][x] = src[0];
1015             dest[1][x] = src[1];
1016             dest[2][x] = src[2];
1017
1018             src += inc_size;
1019         }
1020         src     += srcStride - width * inc_size;
1021         dest[0] += dstStride[0];
1022         dest[1] += dstStride[1];
1023         dest[2] += dstStride[2];
1024     }
1025 }
1026
1027 static int rgbToPlanarRgbWrapper(SwsContext *c, const uint8_t *src[],
1028                                  int srcStride[], int srcSliceY, int srcSliceH,
1029                                  uint8_t *dst[], int dstStride[])
1030 {
1031     int alpha_first = 0;
1032     int stride102[] = { dstStride[1], dstStride[0], dstStride[2] };
1033     int stride201[] = { dstStride[2], dstStride[0], dstStride[1] };
1034     uint8_t *dst102[] = { dst[1] + srcSliceY * dstStride[1],
1035                           dst[0] + srcSliceY * dstStride[0],
1036                           dst[2] + srcSliceY * dstStride[2] };
1037     uint8_t *dst201[] = { dst[2] + srcSliceY * dstStride[2],
1038                           dst[0] + srcSliceY * dstStride[0],
1039                           dst[1] + srcSliceY * dstStride[1] };
1040
1041     switch (c->srcFormat) {
1042     case AV_PIX_FMT_RGB24:
1043         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
1044                        stride201, srcSliceH, alpha_first, 3, c->srcW);
1045         break;
1046     case AV_PIX_FMT_BGR24:
1047         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
1048                        stride102, srcSliceH, alpha_first, 3, c->srcW);
1049         break;
1050     case AV_PIX_FMT_ARGB:
1051         alpha_first = 1;
1052     case AV_PIX_FMT_RGBA:
1053         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201,
1054                        stride201, srcSliceH, alpha_first, 4, c->srcW);
1055         break;
1056     case AV_PIX_FMT_ABGR:
1057         alpha_first = 1;
1058     case AV_PIX_FMT_BGRA:
1059         packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102,
1060                        stride102, srcSliceH, alpha_first, 4, c->srcW);
1061         break;
1062     default:
1063         av_log(c, AV_LOG_ERROR,
1064                "unsupported planar RGB conversion %s -> %s\n",
1065                av_get_pix_fmt_name(c->srcFormat),
1066                av_get_pix_fmt_name(c->dstFormat));
1067     }
1068
1069     return srcSliceH;
1070 }
1071
1072 #define BAYER_GBRG
1073 #define BAYER_8
1074 #define BAYER_RENAME(x) bayer_gbrg8_to_##x
1075 #include "bayer_template.c"
1076
1077 #define BAYER_GBRG
1078 #define BAYER_16LE
1079 #define BAYER_RENAME(x) bayer_gbrg16le_to_##x
1080 #include "bayer_template.c"
1081
1082 #define BAYER_GBRG
1083 #define BAYER_16BE
1084 #define BAYER_RENAME(x) bayer_gbrg16be_to_##x
1085 #include "bayer_template.c"
1086
1087 #define BAYER_GRBG
1088 #define BAYER_8
1089 #define BAYER_RENAME(x) bayer_grbg8_to_##x
1090 #include "bayer_template.c"
1091
1092 #define BAYER_GRBG
1093 #define BAYER_16LE
1094 #define BAYER_RENAME(x) bayer_grbg16le_to_##x
1095 #include "bayer_template.c"
1096
1097 #define BAYER_GRBG
1098 #define BAYER_16BE
1099 #define BAYER_RENAME(x) bayer_grbg16be_to_##x
1100 #include "bayer_template.c"
1101
1102 #define BAYER_BGGR
1103 #define BAYER_8
1104 #define BAYER_RENAME(x) bayer_bggr8_to_##x
1105 #include "bayer_template.c"
1106
1107 #define BAYER_BGGR
1108 #define BAYER_16LE
1109 #define BAYER_RENAME(x) bayer_bggr16le_to_##x
1110 #include "bayer_template.c"
1111
1112 #define BAYER_BGGR
1113 #define BAYER_16BE
1114 #define BAYER_RENAME(x) bayer_bggr16be_to_##x
1115 #include "bayer_template.c"
1116
1117 #define BAYER_RGGB
1118 #define BAYER_8
1119 #define BAYER_RENAME(x) bayer_rggb8_to_##x
1120 #include "bayer_template.c"
1121
1122 #define BAYER_RGGB
1123 #define BAYER_16LE
1124 #define BAYER_RENAME(x) bayer_rggb16le_to_##x
1125 #include "bayer_template.c"
1126
1127 #define BAYER_RGGB
1128 #define BAYER_16BE
1129 #define BAYER_RENAME(x) bayer_rggb16be_to_##x
1130 #include "bayer_template.c"
1131
1132 static int bayer_to_rgb24_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
1133                                   int srcSliceH, uint8_t* dst[], int dstStride[])
1134 {
1135     uint8_t *dstPtr= dst[0] + srcSliceY * dstStride[0];
1136     const uint8_t *srcPtr= src[0];
1137     int i;
1138     void (*copy)       (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
1139     void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width);
1140
1141     switch(c->srcFormat) {
1142 #define CASE(pixfmt, prefix) \
1143     case pixfmt: copy        = bayer_##prefix##_to_rgb24_copy; \
1144                  interpolate = bayer_##prefix##_to_rgb24_interpolate; \
1145                  break;
1146     CASE(AV_PIX_FMT_BAYER_BGGR8,    bggr8)
1147     CASE(AV_PIX_FMT_BAYER_BGGR16LE, bggr16le)
1148     CASE(AV_PIX_FMT_BAYER_BGGR16BE, bggr16be)
1149     CASE(AV_PIX_FMT_BAYER_RGGB8,    rggb8)
1150     CASE(AV_PIX_FMT_BAYER_RGGB16LE, rggb16le)
1151     CASE(AV_PIX_FMT_BAYER_RGGB16BE, rggb16be)
1152     CASE(AV_PIX_FMT_BAYER_GBRG8,    gbrg8)
1153     CASE(AV_PIX_FMT_BAYER_GBRG16LE, gbrg16le)
1154     CASE(AV_PIX_FMT_BAYER_GBRG16BE, gbrg16be)
1155     CASE(AV_PIX_FMT_BAYER_GRBG8,    grbg8)
1156     CASE(AV_PIX_FMT_BAYER_GRBG16LE, grbg16le)
1157     CASE(AV_PIX_FMT_BAYER_GRBG16BE, grbg16be)
1158 #undef CASE
1159     default: return 0;
1160     }
1161
1162     av_assert0(srcSliceH > 1);
1163
1164     copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
1165     srcPtr += 2 * srcStride[0];
1166     dstPtr += 2 * dstStride[0];
1167
1168     for (i = 2; i < srcSliceH - 2; i += 2) {
1169         interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
1170         srcPtr += 2 * srcStride[0];
1171         dstPtr += 2 * dstStride[0];
1172     }
1173
1174     if (i + 1 == srcSliceH) {
1175         copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW);
1176     } else if (i < srcSliceH)
1177         copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW);
1178     return srcSliceH;
1179 }
1180
1181 static int bayer_to_yv12_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
1182                                  int srcSliceH, uint8_t* dst[], int dstStride[])
1183 {
1184     const uint8_t *srcPtr= src[0];
1185     uint8_t *dstY= dst[0] + srcSliceY * dstStride[0];
1186     uint8_t *dstU= dst[1] + srcSliceY * dstStride[1] / 2;
1187     uint8_t *dstV= dst[2] + srcSliceY * dstStride[2] / 2;
1188     int i;
1189     void (*copy)       (const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, int32_t *rgb2yuv);
1190     void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, int32_t *rgb2yuv);
1191
1192     switch(c->srcFormat) {
1193 #define CASE(pixfmt, prefix) \
1194     case pixfmt: copy        = bayer_##prefix##_to_yv12_copy; \
1195                  interpolate = bayer_##prefix##_to_yv12_interpolate; \
1196                  break;
1197     CASE(AV_PIX_FMT_BAYER_BGGR8,    bggr8)
1198     CASE(AV_PIX_FMT_BAYER_BGGR16LE, bggr16le)
1199     CASE(AV_PIX_FMT_BAYER_BGGR16BE, bggr16be)
1200     CASE(AV_PIX_FMT_BAYER_RGGB8,    rggb8)
1201     CASE(AV_PIX_FMT_BAYER_RGGB16LE, rggb16le)
1202     CASE(AV_PIX_FMT_BAYER_RGGB16BE, rggb16be)
1203     CASE(AV_PIX_FMT_BAYER_GBRG8,    gbrg8)
1204     CASE(AV_PIX_FMT_BAYER_GBRG16LE, gbrg16le)
1205     CASE(AV_PIX_FMT_BAYER_GBRG16BE, gbrg16be)
1206     CASE(AV_PIX_FMT_BAYER_GRBG8,    grbg8)
1207     CASE(AV_PIX_FMT_BAYER_GRBG16LE, grbg16le)
1208     CASE(AV_PIX_FMT_BAYER_GRBG16BE, grbg16be)
1209 #undef CASE
1210     default: return 0;
1211     }
1212
1213     av_assert0(srcSliceH > 1);
1214
1215     copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
1216     srcPtr += 2 * srcStride[0];
1217     dstY   += 2 * dstStride[0];
1218     dstU   +=     dstStride[1];
1219     dstV   +=     dstStride[1];
1220
1221     for (i = 2; i < srcSliceH - 2; i += 2) {
1222         interpolate(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
1223         srcPtr += 2 * srcStride[0];
1224         dstY   += 2 * dstStride[0];
1225         dstU   +=     dstStride[1];
1226         dstV   +=     dstStride[1];
1227     }
1228
1229     if (i + 1 == srcSliceH) {
1230         copy(srcPtr, -srcStride[0], dstY, dstU, dstV, -dstStride[0], c->srcW, c->input_rgb2yuv_table);
1231     } else if (i < srcSliceH)
1232         copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table);
1233     return srcSliceH;
1234 }
1235
1236 #define isRGBA32(x) (            \
1237            (x) == AV_PIX_FMT_ARGB   \
1238         || (x) == AV_PIX_FMT_RGBA   \
1239         || (x) == AV_PIX_FMT_BGRA   \
1240         || (x) == AV_PIX_FMT_ABGR   \
1241         )
1242
1243 #define isRGBA64(x) (                \
1244            (x) == AV_PIX_FMT_RGBA64LE   \
1245         || (x) == AV_PIX_FMT_RGBA64BE   \
1246         || (x) == AV_PIX_FMT_BGRA64LE   \
1247         || (x) == AV_PIX_FMT_BGRA64BE   \
1248         )
1249
1250 #define isRGB48(x) (                \
1251            (x) == AV_PIX_FMT_RGB48LE   \
1252         || (x) == AV_PIX_FMT_RGB48BE   \
1253         || (x) == AV_PIX_FMT_BGR48LE   \
1254         || (x) == AV_PIX_FMT_BGR48BE   \
1255         )
1256
1257 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
1258 typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int);
1259 static rgbConvFn findRgbConvFn(SwsContext *c)
1260 {
1261     const enum AVPixelFormat srcFormat = c->srcFormat;
1262     const enum AVPixelFormat dstFormat = c->dstFormat;
1263     const int srcId = c->srcFormatBpp;
1264     const int dstId = c->dstFormatBpp;
1265     rgbConvFn conv = NULL;
1266
1267 #define IS_NOT_NE(bpp, desc) \
1268     (((bpp + 7) >> 3) == 2 && \
1269      (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN))
1270
1271 #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst)
1272
1273     if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
1274         if (     CONV_IS(ABGR, RGBA)
1275               || CONV_IS(ARGB, BGRA)
1276               || CONV_IS(BGRA, ARGB)
1277               || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
1278         else if (CONV_IS(ABGR, ARGB)
1279               || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
1280         else if (CONV_IS(ABGR, BGRA)
1281               || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
1282         else if (CONV_IS(BGRA, RGBA)
1283               || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
1284         else if (CONV_IS(BGRA, ABGR)
1285               || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
1286     } else if (isRGB48(srcFormat) && isRGB48(dstFormat)) {
1287         if      (CONV_IS(RGB48LE, BGR48LE)
1288               || CONV_IS(BGR48LE, RGB48LE)
1289               || CONV_IS(RGB48BE, BGR48BE)
1290               || CONV_IS(BGR48BE, RGB48BE)) conv = rgb48tobgr48_nobswap;
1291         else if (CONV_IS(RGB48LE, BGR48BE)
1292               || CONV_IS(BGR48LE, RGB48BE)
1293               || CONV_IS(RGB48BE, BGR48LE)
1294               || CONV_IS(BGR48BE, RGB48LE)) conv = rgb48tobgr48_bswap;
1295     } else if (isRGB48(srcFormat) && isRGBA64(dstFormat)) {
1296         if      (CONV_IS(RGB48LE, BGRA64LE)
1297               || CONV_IS(BGR48LE, RGBA64LE)
1298               || CONV_IS(RGB48BE, BGRA64BE)
1299               || CONV_IS(BGR48BE, RGBA64BE)) conv = rgb48tobgr64_nobswap;
1300         else if (CONV_IS(RGB48LE, BGRA64BE)
1301               || CONV_IS(BGR48LE, RGBA64BE)
1302               || CONV_IS(RGB48BE, BGRA64LE)
1303               || CONV_IS(BGR48BE, RGBA64LE)) conv = rgb48tobgr64_bswap;
1304         if      (CONV_IS(RGB48LE, RGBA64LE)
1305               || CONV_IS(BGR48LE, BGRA64LE)
1306               || CONV_IS(RGB48BE, RGBA64BE)
1307               || CONV_IS(BGR48BE, BGRA64BE)) conv = rgb48to64_nobswap;
1308         else if (CONV_IS(RGB48LE, RGBA64BE)
1309               || CONV_IS(BGR48LE, BGRA64BE)
1310               || CONV_IS(RGB48BE, RGBA64LE)
1311               || CONV_IS(BGR48BE, BGRA64LE)) conv = rgb48to64_bswap;
1312     } else if (isRGBA64(srcFormat) && isRGB48(dstFormat)) {
1313         if      (CONV_IS(RGBA64LE, BGR48LE)
1314               || CONV_IS(BGRA64LE, RGB48LE)
1315               || CONV_IS(RGBA64BE, BGR48BE)
1316               || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap;
1317         else if (CONV_IS(RGBA64LE, BGR48BE)
1318               || CONV_IS(BGRA64LE, RGB48BE)
1319               || CONV_IS(RGBA64BE, BGR48LE)
1320               || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap;
1321         else if (CONV_IS(RGBA64LE, RGB48LE)
1322               || CONV_IS(BGRA64LE, BGR48LE)
1323               || CONV_IS(RGBA64BE, RGB48BE)
1324               || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap;
1325         else if (CONV_IS(RGBA64LE, RGB48BE)
1326               || CONV_IS(BGRA64LE, BGR48BE)
1327               || CONV_IS(RGBA64BE, RGB48LE)
1328               || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap;
1329     } else
1330     /* BGR -> BGR */
1331     if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
1332         (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
1333         switch (srcId | (dstId << 16)) {
1334         case 0x000F000C: conv = rgb12to15; break;
1335         case 0x000F0010: conv = rgb16to15; break;
1336         case 0x000F0018: conv = rgb24to15; break;
1337         case 0x000F0020: conv = rgb32to15; break;
1338         case 0x0010000F: conv = rgb15to16; break;
1339         case 0x00100018: conv = rgb24to16; break;
1340         case 0x00100020: conv = rgb32to16; break;
1341         case 0x0018000F: conv = rgb15to24; break;
1342         case 0x00180010: conv = rgb16to24; break;
1343         case 0x00180020: conv = rgb32to24; break;
1344         case 0x0020000F: conv = rgb15to32; break;
1345         case 0x00200010: conv = rgb16to32; break;
1346         case 0x00200018: conv = rgb24to32; break;
1347         }
1348     } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
1349                (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
1350         switch (srcId | (dstId << 16)) {
1351         case 0x000C000C: conv = rgb12tobgr12; break;
1352         case 0x000F000F: conv = rgb15tobgr15; break;
1353         case 0x000F0010: conv = rgb16tobgr15; break;
1354         case 0x000F0018: conv = rgb24tobgr15; break;
1355         case 0x000F0020: conv = rgb32tobgr15; break;
1356         case 0x0010000F: conv = rgb15tobgr16; break;
1357         case 0x00100010: conv = rgb16tobgr16; break;
1358         case 0x00100018: conv = rgb24tobgr16; break;
1359         case 0x00100020: conv = rgb32tobgr16; break;
1360         case 0x0018000F: conv = rgb15tobgr24; break;
1361         case 0x00180010: conv = rgb16tobgr24; break;
1362         case 0x00180018: conv = rgb24tobgr24; break;
1363         case 0x00180020: conv = rgb32tobgr24; break;
1364         case 0x0020000F: conv = rgb15tobgr32; break;
1365         case 0x00200010: conv = rgb16tobgr32; break;
1366         case 0x00200018: conv = rgb24tobgr32; break;
1367         }
1368     }
1369
1370     if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) && !isRGBA32(srcFormat) && ALT32_CORR<0)
1371         return NULL;
1372
1373     // Maintain symmetry between endianness
1374     if (c->flags & SWS_BITEXACT)
1375         if ((dstFormat == AV_PIX_FMT_RGB32   || dstFormat == AV_PIX_FMT_BGR32  ) && !isRGBA32(srcFormat) && ALT32_CORR>0)
1376             return NULL;
1377
1378     return conv;
1379 }
1380
1381 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
1382 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
1383                            int srcSliceY, int srcSliceH, uint8_t *dst[],
1384                            int dstStride[])
1385
1386 {
1387     const enum AVPixelFormat srcFormat = c->srcFormat;
1388     const enum AVPixelFormat dstFormat = c->dstFormat;
1389     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
1390     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
1391     const int srcBpp = (c->srcFormatBpp + 7) >> 3;
1392     const int dstBpp = (c->dstFormatBpp + 7) >> 3;
1393     rgbConvFn conv = findRgbConvFn(c);
1394
1395     if (!conv) {
1396         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
1397                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
1398     } else {
1399         const uint8_t *srcPtr = src[0];
1400               uint8_t *dstPtr = dst[0];
1401         int src_bswap = IS_NOT_NE(c->srcFormatBpp, desc_src);
1402         int dst_bswap = IS_NOT_NE(c->dstFormatBpp, desc_dst);
1403
1404         if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) &&
1405             !isRGBA32(dstFormat))
1406             srcPtr += ALT32_CORR;
1407
1408         if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) &&
1409             !isRGBA32(srcFormat)) {
1410             int i;
1411             av_assert0(ALT32_CORR == 1);
1412             for (i = 0; i < srcSliceH; i++)
1413                 dstPtr[dstStride[0] * (srcSliceY + i)] = 255;
1414             dstPtr += ALT32_CORR;
1415         }
1416
1417         if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
1418             !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap)
1419             conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
1420                  (srcSliceH - 1) * srcStride[0] + c->srcW * srcBpp);
1421         else {
1422             int i, j;
1423             dstPtr += dstStride[0] * srcSliceY;
1424
1425             for (i = 0; i < srcSliceH; i++) {
1426                 if(src_bswap) {
1427                     for(j=0; j<c->srcW; j++)
1428                         ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]);
1429                     conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp);
1430                 }else
1431                     conv(srcPtr, dstPtr, c->srcW * srcBpp);
1432                 if(dst_bswap)
1433                     for(j=0; j<c->srcW; j++)
1434                         ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]);
1435                 srcPtr += srcStride[0];
1436                 dstPtr += dstStride[0];
1437             }
1438         }
1439     }
1440     return srcSliceH;
1441 }
1442
1443 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
1444                               int srcStride[], int srcSliceY, int srcSliceH,
1445                               uint8_t *dst[], int dstStride[])
1446 {
1447     ff_rgb24toyv12(
1448         src[0],
1449         dst[0] +  srcSliceY       * dstStride[0],
1450         dst[1] + (srcSliceY >> 1) * dstStride[1],
1451         dst[2] + (srcSliceY >> 1) * dstStride[2],
1452         c->srcW, srcSliceH,
1453         dstStride[0], dstStride[1], srcStride[0],
1454         c->input_rgb2yuv_table);
1455     if (dst[3])
1456         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
1457     return srcSliceH;
1458 }
1459
1460 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
1461                              int srcStride[], int srcSliceY, int srcSliceH,
1462                              uint8_t *dst[], int dstStride[])
1463 {
1464     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
1465               dst[0], dstStride[0]);
1466
1467     planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
1468              srcSliceH >> 2, srcStride[1], dstStride[1]);
1469     planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
1470              srcSliceH >> 2, srcStride[2], dstStride[2]);
1471     if (dst[3])
1472         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
1473     return srcSliceH;
1474 }
1475
1476 /* unscaled copy like stuff (assumes nearly identical formats) */
1477 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
1478                              int srcStride[], int srcSliceY, int srcSliceH,
1479                              uint8_t *dst[], int dstStride[])
1480 {
1481     if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
1482         memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
1483     else {
1484         int i;
1485         const uint8_t *srcPtr = src[0];
1486         uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
1487         int length = 0;
1488
1489         /* universal length finder */
1490         while (length + c->srcW <= FFABS(dstStride[0]) &&
1491                length + c->srcW <= FFABS(srcStride[0]))
1492             length += c->srcW;
1493         av_assert1(length != 0);
1494
1495         for (i = 0; i < srcSliceH; i++) {
1496             memcpy(dstPtr, srcPtr, length);
1497             srcPtr += srcStride[0];
1498             dstPtr += dstStride[0];
1499         }
1500     }
1501     return srcSliceH;
1502 }
1503
1504 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
1505     uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
1506     int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
1507     for (i = 0; i < height; i++) {\
1508         const uint8_t *dither= dithers[src_depth-9][i&7];\
1509         for (j = 0; j < length-7; j+=8){\
1510             dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
1511             dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
1512             dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
1513             dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
1514             dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
1515             dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
1516             dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
1517             dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
1518         }\
1519         for (; j < length; j++)\
1520             dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
1521         dst += dstStride;\
1522         src += srcStride;\
1523     }
1524
1525 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
1526                              int srcStride[], int srcSliceY, int srcSliceH,
1527                              uint8_t *dst[], int dstStride[])
1528 {
1529     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
1530     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
1531     int plane, i, j;
1532     for (plane = 0; plane < 4; plane++) {
1533         int length = (plane == 0 || plane == 3) ? c->srcW  : AV_CEIL_RSHIFT(c->srcW,   c->chrDstHSubSample);
1534         int y =      (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample);
1535         int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample);
1536         const uint8_t *srcPtr = src[plane];
1537         uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
1538         int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0);
1539
1540         if (!dst[plane])
1541             continue;
1542         // ignore palette for GRAY8
1543         if (plane == 1 && !dst[2]) continue;
1544         if (!src[plane] || (plane == 1 && !src[2])) {
1545             if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) {
1546                 fillPlane16(dst[plane], dstStride[plane], length, height, y,
1547                         plane == 3, desc_dst->comp[plane].depth,
1548                         isBE(c->dstFormat));
1549             } else {
1550                 fillPlane(dst[plane], dstStride[plane], length, height, y,
1551                         (plane == 3) ? 255 : 128);
1552             }
1553         } else {
1554             if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
1555                || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
1556             ) {
1557                 const int src_depth = desc_src->comp[plane].depth;
1558                 const int dst_depth = desc_dst->comp[plane].depth;
1559                 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
1560                 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
1561
1562                 if (dst_depth == 8) {
1563                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
1564                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
1565                     } else {
1566                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
1567                     }
1568                 } else if (src_depth == 8) {
1569                     for (i = 0; i < height; i++) {
1570                         #define COPY816(w)\
1571                         if (shiftonly) {\
1572                             for (j = 0; j < length; j++)\
1573                                 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
1574                         } else {\
1575                             for (j = 0; j < length; j++)\
1576                                 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
1577                                                (srcPtr[j]>>(2*8-dst_depth)));\
1578                         }
1579                         if(isBE(c->dstFormat)){
1580                             COPY816(AV_WB16)
1581                         } else {
1582                             COPY816(AV_WL16)
1583                         }
1584                         dstPtr2 += dstStride[plane]/2;
1585                         srcPtr  += srcStride[plane];
1586                     }
1587                 } else if (src_depth <= dst_depth) {
1588                     for (i = 0; i < height; i++) {
1589                         j = 0;
1590                         if(isBE(c->srcFormat) == HAVE_BIGENDIAN &&
1591                            isBE(c->dstFormat) == HAVE_BIGENDIAN &&
1592                            shiftonly) {
1593                              unsigned shift = dst_depth - src_depth;
1594 #if HAVE_FAST_64BIT
1595 #define FAST_COPY_UP(shift) \
1596     for (; j < length - 3; j += 4) { \
1597         uint64_t v = AV_RN64A(srcPtr2 + j); \
1598         AV_WN64A(dstPtr2 + j, v << shift); \
1599     }
1600 #else
1601 #define FAST_COPY_UP(shift) \
1602     for (; j < length - 1; j += 2) { \
1603         uint32_t v = AV_RN32A(srcPtr2 + j); \
1604         AV_WN32A(dstPtr2 + j, v << shift); \
1605     }
1606 #endif
1607                              switch (shift)
1608                              {
1609                              case 6: FAST_COPY_UP(6); break;
1610                              case 7: FAST_COPY_UP(7); break;
1611                              }
1612                         }
1613 #define COPY_UP(r,w) \
1614     if(shiftonly){\
1615         for (; j < length; j++){ \
1616             unsigned int v= r(&srcPtr2[j]);\
1617             w(&dstPtr2[j], v<<(dst_depth-src_depth));\
1618         }\
1619     }else{\
1620         for (; j < length; j++){ \
1621             unsigned int v= r(&srcPtr2[j]);\
1622             w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
1623                         (v>>(2*src_depth-dst_depth)));\
1624         }\
1625     }
1626                         if(isBE(c->srcFormat)){
1627                             if(isBE(c->dstFormat)){
1628                                 COPY_UP(AV_RB16, AV_WB16)
1629                             } else {
1630                                 COPY_UP(AV_RB16, AV_WL16)
1631                             }
1632                         } else {
1633                             if(isBE(c->dstFormat)){
1634                                 COPY_UP(AV_RL16, AV_WB16)
1635                             } else {
1636                                 COPY_UP(AV_RL16, AV_WL16)
1637                             }
1638                         }
1639                         dstPtr2 += dstStride[plane]/2;
1640                         srcPtr2 += srcStride[plane]/2;
1641                     }
1642                 } else {
1643                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
1644                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
1645                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
1646                         } else {
1647                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
1648                         }
1649                     }else{
1650                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
1651                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
1652                         } else {
1653                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
1654                         }
1655                     }
1656                 }
1657             } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
1658                       isBE(c->srcFormat) != isBE(c->dstFormat)) {
1659
1660                 for (i = 0; i < height; i++) {
1661                     for (j = 0; j < length; j++)
1662                         ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
1663                     srcPtr += srcStride[plane];
1664                     dstPtr += dstStride[plane];
1665                 }
1666             } else if (dstStride[plane] == srcStride[plane] &&
1667                        srcStride[plane] > 0 && srcStride[plane] == length) {
1668                 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
1669                        height * dstStride[plane]);
1670             } else {
1671                 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
1672                     length *= 2;
1673                 else if (desc_src->comp[0].depth == 1)
1674                     length >>= 3; // monowhite/black
1675                 for (i = 0; i < height; i++) {
1676                     memcpy(dstPtr, srcPtr, length);
1677                     srcPtr += srcStride[plane];
1678                     dstPtr += dstStride[plane];
1679                 }
1680             }
1681         }
1682     }
1683     return srcSliceH;
1684 }
1685
1686
1687 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt)          \
1688     ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) ||     \
1689      (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
1690
1691
1692 void ff_get_unscaled_swscale(SwsContext *c)
1693 {
1694     const enum AVPixelFormat srcFormat = c->srcFormat;
1695     const enum AVPixelFormat dstFormat = c->dstFormat;
1696     const int flags = c->flags;
1697     const int dstH = c->dstH;
1698     int needsDither;
1699
1700     needsDither = isAnyRGB(dstFormat) &&
1701             c->dstFormatBpp < 24 &&
1702            (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
1703
1704     /* yv12_to_nv12 */
1705     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
1706         (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
1707         c->swscale = planarToNv12Wrapper;
1708     }
1709     /* nv12_to_yv12 */
1710     if (dstFormat == AV_PIX_FMT_YUV420P &&
1711         (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) {
1712         c->swscale = nv12ToPlanarWrapper;
1713     }
1714     /* yuv2bgr */
1715     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
1716          srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
1717         !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) {
1718         c->swscale = ff_yuv2rgb_get_func_ptr(c);
1719     }
1720     /* yuv420p10_to_p010 */
1721     if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10) &&
1722         dstFormat == AV_PIX_FMT_P010) {
1723         c->swscale = planarToP010Wrapper;
1724     }
1725     /* yuv420p_to_p010le */
1726     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
1727         dstFormat == AV_PIX_FMT_P010LE) {
1728         c->swscale = planar8ToP01xleWrapper;
1729     }
1730
1731     if (srcFormat == AV_PIX_FMT_YUV410P && !(dstH & 3) &&
1732         (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
1733         !(flags & SWS_BITEXACT)) {
1734         c->swscale = yvu9ToYv12Wrapper;
1735     }
1736
1737     /* bgr24toYV12 */
1738     if (srcFormat == AV_PIX_FMT_BGR24 &&
1739         (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
1740         !(flags & SWS_ACCURATE_RND))
1741         c->swscale = bgr24ToYv12Wrapper;
1742
1743     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
1744     if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
1745         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
1746         c->swscale = rgbToRgbWrapper;
1747
1748     /* RGB to planar RGB */
1749     if ((srcFormat == AV_PIX_FMT_GBRP && dstFormat == AV_PIX_FMT_GBRAP) ||
1750         (srcFormat == AV_PIX_FMT_GBRAP && dstFormat == AV_PIX_FMT_GBRP))
1751         c->swscale = planarRgbToplanarRgbWrapper;
1752
1753 #define isByteRGB(f) (             \
1754         f == AV_PIX_FMT_RGB32   || \
1755         f == AV_PIX_FMT_RGB32_1 || \
1756         f == AV_PIX_FMT_RGB24   || \
1757         f == AV_PIX_FMT_BGR32   || \
1758         f == AV_PIX_FMT_BGR32_1 || \
1759         f == AV_PIX_FMT_BGR24)
1760
1761     if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat))
1762         c->swscale = planarRgbToRgbWrapper;
1763
1764     if ((srcFormat == AV_PIX_FMT_RGB48LE  || srcFormat == AV_PIX_FMT_RGB48BE  ||
1765          srcFormat == AV_PIX_FMT_BGR48LE  || srcFormat == AV_PIX_FMT_BGR48BE  ||
1766          srcFormat == AV_PIX_FMT_RGBA64LE || srcFormat == AV_PIX_FMT_RGBA64BE ||
1767          srcFormat == AV_PIX_FMT_BGRA64LE || srcFormat == AV_PIX_FMT_BGRA64BE) &&
1768         (dstFormat == AV_PIX_FMT_GBRP9LE  || dstFormat == AV_PIX_FMT_GBRP9BE  ||
1769          dstFormat == AV_PIX_FMT_GBRP10LE || dstFormat == AV_PIX_FMT_GBRP10BE ||
1770          dstFormat == AV_PIX_FMT_GBRP12LE || dstFormat == AV_PIX_FMT_GBRP12BE ||
1771          dstFormat == AV_PIX_FMT_GBRP14LE || dstFormat == AV_PIX_FMT_GBRP14BE ||
1772          dstFormat == AV_PIX_FMT_GBRP16LE || dstFormat == AV_PIX_FMT_GBRP16BE ||
1773          dstFormat == AV_PIX_FMT_GBRAP12LE || dstFormat == AV_PIX_FMT_GBRAP12BE ||
1774          dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE ))
1775         c->swscale = Rgb16ToPlanarRgb16Wrapper;
1776
1777     if ((srcFormat == AV_PIX_FMT_GBRP9LE  || srcFormat == AV_PIX_FMT_GBRP9BE  ||
1778          srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE ||
1779          srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE ||
1780          srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE ||
1781          srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE ||
1782          srcFormat == AV_PIX_FMT_GBRAP12LE || srcFormat == AV_PIX_FMT_GBRAP12BE ||
1783          srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) &&
1784         (dstFormat == AV_PIX_FMT_RGB48LE  || dstFormat == AV_PIX_FMT_RGB48BE  ||
1785          dstFormat == AV_PIX_FMT_BGR48LE  || dstFormat == AV_PIX_FMT_BGR48BE  ||
1786          dstFormat == AV_PIX_FMT_RGBA64LE || dstFormat == AV_PIX_FMT_RGBA64BE ||
1787          dstFormat == AV_PIX_FMT_BGRA64LE || dstFormat == AV_PIX_FMT_BGRA64BE))
1788         c->swscale = planarRgb16ToRgb16Wrapper;
1789
1790     if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth == 8 &&
1791         isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP)
1792         c->swscale = rgbToPlanarRgbWrapper;
1793
1794     if (isBayer(srcFormat)) {
1795         if (dstFormat == AV_PIX_FMT_RGB24)
1796             c->swscale = bayer_to_rgb24_wrapper;
1797         else if (dstFormat == AV_PIX_FMT_YUV420P)
1798             c->swscale = bayer_to_yv12_wrapper;
1799         else if (!isBayer(dstFormat)) {
1800             av_log(c, AV_LOG_ERROR, "unsupported bayer conversion\n");
1801             av_assert0(0);
1802         }
1803     }
1804
1805     /* bswap 16 bits per pixel/component packed formats */
1806     if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_BGGR16) ||
1807         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_RGGB16) ||
1808         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GBRG16) ||
1809         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GRBG16) ||
1810         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) ||
1811         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48)  ||
1812         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
1813         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) ||
1814         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) ||
1815         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
1816         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY9)  ||
1817         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY10) ||
1818         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY12) ||
1819         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) ||
1820         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16)   ||
1821         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_AYUV64) ||
1822         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP9)  ||
1823         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP10) ||
1824         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) ||
1825         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) ||
1826         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) ||
1827         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP12) ||
1828         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) ||
1829         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
1830         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48)  ||
1831         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
1832         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) ||
1833         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) ||
1834         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
1835         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12)  ||
1836         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P9)  ||
1837         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P10) ||
1838         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P12) ||
1839         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P14) ||
1840         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P16) ||
1841         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P9)  ||
1842         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P10) ||
1843         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P12) ||
1844         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P14) ||
1845         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P16) ||
1846         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV440P10) ||
1847         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV440P12) ||
1848         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P9)  ||
1849         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P10) ||
1850         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P12) ||
1851         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P14) ||
1852         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16))
1853         c->swscale = packed_16bpc_bswap;
1854
1855     if (usePal(srcFormat) && isByteRGB(dstFormat))
1856         c->swscale = palToRgbWrapper;
1857
1858     if (srcFormat == AV_PIX_FMT_YUV422P) {
1859         if (dstFormat == AV_PIX_FMT_YUYV422)
1860             c->swscale = yuv422pToYuy2Wrapper;
1861         else if (dstFormat == AV_PIX_FMT_UYVY422)
1862             c->swscale = yuv422pToUyvyWrapper;
1863     }
1864
1865     /* LQ converters if -sws 0 or -sws 4*/
1866     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
1867         /* yv12_to_yuy2 */
1868         if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) {
1869             if (dstFormat == AV_PIX_FMT_YUYV422)
1870                 c->swscale = planarToYuy2Wrapper;
1871             else if (dstFormat == AV_PIX_FMT_UYVY422)
1872                 c->swscale = planarToUyvyWrapper;
1873         }
1874     }
1875     if (srcFormat == AV_PIX_FMT_YUYV422 &&
1876        (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
1877         c->swscale = yuyvToYuv420Wrapper;
1878     if (srcFormat == AV_PIX_FMT_UYVY422 &&
1879        (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
1880         c->swscale = uyvyToYuv420Wrapper;
1881     if (srcFormat == AV_PIX_FMT_YUYV422 && dstFormat == AV_PIX_FMT_YUV422P)
1882         c->swscale = yuyvToYuv422Wrapper;
1883     if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P)
1884         c->swscale = uyvyToYuv422Wrapper;
1885
1886 #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_YA8 && (x) != AV_PIX_FMT_YA16LE && (x) != AV_PIX_FMT_YA16BE)
1887     /* simple copy */
1888     if ( srcFormat == dstFormat ||
1889         (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) ||
1890         (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) ||
1891         (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
1892         (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) ||
1893         (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) ||
1894         (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
1895          c->chrDstHSubSample == c->chrSrcHSubSample &&
1896          c->chrDstVSubSample == c->chrSrcVSubSample &&
1897          dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
1898          dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE &&
1899          dstFormat != AV_PIX_FMT_P016LE && dstFormat != AV_PIX_FMT_P016BE &&
1900          srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 &&
1901          srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE &&
1902          srcFormat != AV_PIX_FMT_P016LE && srcFormat != AV_PIX_FMT_P016BE))
1903     {
1904         if (isPacked(c->srcFormat))
1905             c->swscale = packedCopyWrapper;
1906         else /* Planar YUV or gray */
1907             c->swscale = planarCopyWrapper;
1908     }
1909
1910     if (ARCH_PPC)
1911         ff_get_unscaled_swscale_ppc(c);
1912      if (ARCH_ARM)
1913          ff_get_unscaled_swscale_arm(c);
1914     if (ARCH_AARCH64)
1915         ff_get_unscaled_swscale_aarch64(c);
1916 }
1917
1918 /* Convert the palette to the same packed 32-bit format as the palette */
1919 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
1920                                    int num_pixels, const uint8_t *palette)
1921 {
1922     int i;
1923
1924     for (i = 0; i < num_pixels; i++)
1925         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
1926 }
1927
1928 /* Palette format: ABCD -> dst format: ABC */
1929 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
1930                                    int num_pixels, const uint8_t *palette)
1931 {
1932     int i;
1933
1934     for (i = 0; i < num_pixels; i++) {
1935         //FIXME slow?
1936         dst[0] = palette[src[i] * 4 + 0];
1937         dst[1] = palette[src[i] * 4 + 1];
1938         dst[2] = palette[src[i] * 4 + 2];
1939         dst += 3;
1940     }
1941 }