OSDN Git Service

Merge commit 'ca6ae3b77a7e6600e517723b90e57527a47809de'
[android-x86/external-ffmpeg.git] / 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 (isRGBA64(srcFormat) && isRGB48(dstFormat)) {
1296         if      (CONV_IS(RGBA64LE, BGR48LE)
1297               || CONV_IS(BGRA64LE, RGB48LE)
1298               || CONV_IS(RGBA64BE, BGR48BE)
1299               || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap;
1300         else if (CONV_IS(RGBA64LE, BGR48BE)
1301               || CONV_IS(BGRA64LE, RGB48BE)
1302               || CONV_IS(RGBA64BE, BGR48LE)
1303               || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap;
1304         else if (CONV_IS(RGBA64LE, RGB48LE)
1305               || CONV_IS(BGRA64LE, BGR48LE)
1306               || CONV_IS(RGBA64BE, RGB48BE)
1307               || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap;
1308         else if (CONV_IS(RGBA64LE, RGB48BE)
1309               || CONV_IS(BGRA64LE, BGR48BE)
1310               || CONV_IS(RGBA64BE, RGB48LE)
1311               || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap;
1312     } else
1313     /* BGR -> BGR */
1314     if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
1315         (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
1316         switch (srcId | (dstId << 16)) {
1317         case 0x000F000C: conv = rgb12to15; break;
1318         case 0x000F0010: conv = rgb16to15; break;
1319         case 0x000F0018: conv = rgb24to15; break;
1320         case 0x000F0020: conv = rgb32to15; break;
1321         case 0x0010000F: conv = rgb15to16; break;
1322         case 0x00100018: conv = rgb24to16; break;
1323         case 0x00100020: conv = rgb32to16; break;
1324         case 0x0018000F: conv = rgb15to24; break;
1325         case 0x00180010: conv = rgb16to24; break;
1326         case 0x00180020: conv = rgb32to24; break;
1327         case 0x0020000F: conv = rgb15to32; break;
1328         case 0x00200010: conv = rgb16to32; break;
1329         case 0x00200018: conv = rgb24to32; break;
1330         }
1331     } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
1332                (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
1333         switch (srcId | (dstId << 16)) {
1334         case 0x000C000C: conv = rgb12tobgr12; break;
1335         case 0x000F000F: conv = rgb15tobgr15; break;
1336         case 0x000F0010: conv = rgb16tobgr15; break;
1337         case 0x000F0018: conv = rgb24tobgr15; break;
1338         case 0x000F0020: conv = rgb32tobgr15; break;
1339         case 0x0010000F: conv = rgb15tobgr16; break;
1340         case 0x00100010: conv = rgb16tobgr16; break;
1341         case 0x00100018: conv = rgb24tobgr16; break;
1342         case 0x00100020: conv = rgb32tobgr16; break;
1343         case 0x0018000F: conv = rgb15tobgr24; break;
1344         case 0x00180010: conv = rgb16tobgr24; break;
1345         case 0x00180018: conv = rgb24tobgr24; break;
1346         case 0x00180020: conv = rgb32tobgr24; break;
1347         case 0x0020000F: conv = rgb15tobgr32; break;
1348         case 0x00200010: conv = rgb16tobgr32; break;
1349         case 0x00200018: conv = rgb24tobgr32; break;
1350         }
1351     }
1352
1353     if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) && !isRGBA32(srcFormat) && ALT32_CORR<0)
1354         return NULL;
1355
1356     // Maintain symmetry between endianness
1357     if (c->flags & SWS_BITEXACT)
1358         if ((dstFormat == AV_PIX_FMT_RGB32   || dstFormat == AV_PIX_FMT_BGR32  ) && !isRGBA32(srcFormat) && ALT32_CORR>0)
1359             return NULL;
1360
1361     return conv;
1362 }
1363
1364 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
1365 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
1366                            int srcSliceY, int srcSliceH, uint8_t *dst[],
1367                            int dstStride[])
1368
1369 {
1370     const enum AVPixelFormat srcFormat = c->srcFormat;
1371     const enum AVPixelFormat dstFormat = c->dstFormat;
1372     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
1373     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
1374     const int srcBpp = (c->srcFormatBpp + 7) >> 3;
1375     const int dstBpp = (c->dstFormatBpp + 7) >> 3;
1376     rgbConvFn conv = findRgbConvFn(c);
1377
1378     if (!conv) {
1379         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
1380                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
1381     } else {
1382         const uint8_t *srcPtr = src[0];
1383               uint8_t *dstPtr = dst[0];
1384         int src_bswap = IS_NOT_NE(c->srcFormatBpp, desc_src);
1385         int dst_bswap = IS_NOT_NE(c->dstFormatBpp, desc_dst);
1386
1387         if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) &&
1388             !isRGBA32(dstFormat))
1389             srcPtr += ALT32_CORR;
1390
1391         if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) &&
1392             !isRGBA32(srcFormat)) {
1393             int i;
1394             av_assert0(ALT32_CORR == 1);
1395             for (i = 0; i < srcSliceH; i++)
1396                 dstPtr[dstStride[0] * (srcSliceY + i)] = 255;
1397             dstPtr += ALT32_CORR;
1398         }
1399
1400         if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
1401             !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap)
1402             conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
1403                  (srcSliceH - 1) * srcStride[0] + c->srcW * srcBpp);
1404         else {
1405             int i, j;
1406             dstPtr += dstStride[0] * srcSliceY;
1407
1408             for (i = 0; i < srcSliceH; i++) {
1409                 if(src_bswap) {
1410                     for(j=0; j<c->srcW; j++)
1411                         ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]);
1412                     conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp);
1413                 }else
1414                     conv(srcPtr, dstPtr, c->srcW * srcBpp);
1415                 if(dst_bswap)
1416                     for(j=0; j<c->srcW; j++)
1417                         ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]);
1418                 srcPtr += srcStride[0];
1419                 dstPtr += dstStride[0];
1420             }
1421         }
1422     }
1423     return srcSliceH;
1424 }
1425
1426 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
1427                               int srcStride[], int srcSliceY, int srcSliceH,
1428                               uint8_t *dst[], int dstStride[])
1429 {
1430     ff_rgb24toyv12(
1431         src[0],
1432         dst[0] +  srcSliceY       * dstStride[0],
1433         dst[1] + (srcSliceY >> 1) * dstStride[1],
1434         dst[2] + (srcSliceY >> 1) * dstStride[2],
1435         c->srcW, srcSliceH,
1436         dstStride[0], dstStride[1], srcStride[0],
1437         c->input_rgb2yuv_table);
1438     if (dst[3])
1439         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
1440     return srcSliceH;
1441 }
1442
1443 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
1444                              int srcStride[], int srcSliceY, int srcSliceH,
1445                              uint8_t *dst[], int dstStride[])
1446 {
1447     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
1448               dst[0], dstStride[0]);
1449
1450     planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
1451              srcSliceH >> 2, srcStride[1], dstStride[1]);
1452     planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
1453              srcSliceH >> 2, srcStride[2], dstStride[2]);
1454     if (dst[3])
1455         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
1456     return srcSliceH;
1457 }
1458
1459 /* unscaled copy like stuff (assumes nearly identical formats) */
1460 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
1461                              int srcStride[], int srcSliceY, int srcSliceH,
1462                              uint8_t *dst[], int dstStride[])
1463 {
1464     if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
1465         memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
1466     else {
1467         int i;
1468         const uint8_t *srcPtr = src[0];
1469         uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
1470         int length = 0;
1471
1472         /* universal length finder */
1473         while (length + c->srcW <= FFABS(dstStride[0]) &&
1474                length + c->srcW <= FFABS(srcStride[0]))
1475             length += c->srcW;
1476         av_assert1(length != 0);
1477
1478         for (i = 0; i < srcSliceH; i++) {
1479             memcpy(dstPtr, srcPtr, length);
1480             srcPtr += srcStride[0];
1481             dstPtr += dstStride[0];
1482         }
1483     }
1484     return srcSliceH;
1485 }
1486
1487 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
1488     uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
1489     int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
1490     for (i = 0; i < height; i++) {\
1491         const uint8_t *dither= dithers[src_depth-9][i&7];\
1492         for (j = 0; j < length-7; j+=8){\
1493             dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
1494             dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
1495             dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
1496             dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
1497             dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
1498             dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
1499             dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
1500             dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
1501         }\
1502         for (; j < length; j++)\
1503             dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
1504         dst += dstStride;\
1505         src += srcStride;\
1506     }
1507
1508 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
1509                              int srcStride[], int srcSliceY, int srcSliceH,
1510                              uint8_t *dst[], int dstStride[])
1511 {
1512     const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
1513     const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
1514     int plane, i, j;
1515     for (plane = 0; plane < 4; plane++) {
1516         int length = (plane == 0 || plane == 3) ? c->srcW  : AV_CEIL_RSHIFT(c->srcW,   c->chrDstHSubSample);
1517         int y =      (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample);
1518         int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample);
1519         const uint8_t *srcPtr = src[plane];
1520         uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
1521         int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0);
1522
1523         if (!dst[plane])
1524             continue;
1525         // ignore palette for GRAY8
1526         if (plane == 1 && !dst[2]) continue;
1527         if (!src[plane] || (plane == 1 && !src[2])) {
1528             if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) {
1529                 fillPlane16(dst[plane], dstStride[plane], length, height, y,
1530                         plane == 3, desc_dst->comp[plane].depth,
1531                         isBE(c->dstFormat));
1532             } else {
1533                 fillPlane(dst[plane], dstStride[plane], length, height, y,
1534                         (plane == 3) ? 255 : 128);
1535             }
1536         } else {
1537             if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
1538                || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
1539             ) {
1540                 const int src_depth = desc_src->comp[plane].depth;
1541                 const int dst_depth = desc_dst->comp[plane].depth;
1542                 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
1543                 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
1544
1545                 if (dst_depth == 8) {
1546                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
1547                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
1548                     } else {
1549                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
1550                     }
1551                 } else if (src_depth == 8) {
1552                     for (i = 0; i < height; i++) {
1553                         #define COPY816(w)\
1554                         if (shiftonly) {\
1555                             for (j = 0; j < length; j++)\
1556                                 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
1557                         } else {\
1558                             for (j = 0; j < length; j++)\
1559                                 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
1560                                                (srcPtr[j]>>(2*8-dst_depth)));\
1561                         }
1562                         if(isBE(c->dstFormat)){
1563                             COPY816(AV_WB16)
1564                         } else {
1565                             COPY816(AV_WL16)
1566                         }
1567                         dstPtr2 += dstStride[plane]/2;
1568                         srcPtr  += srcStride[plane];
1569                     }
1570                 } else if (src_depth <= dst_depth) {
1571                     for (i = 0; i < height; i++) {
1572                         j = 0;
1573                         if(isBE(c->srcFormat) == HAVE_BIGENDIAN &&
1574                            isBE(c->dstFormat) == HAVE_BIGENDIAN &&
1575                            shiftonly) {
1576                              unsigned shift = dst_depth - src_depth;
1577 #if HAVE_FAST_64BIT
1578 #define FAST_COPY_UP(shift) \
1579     for (; j < length - 3; j += 4) { \
1580         uint64_t v = AV_RN64A(srcPtr2 + j); \
1581         AV_WN64A(dstPtr2 + j, v << shift); \
1582     }
1583 #else
1584 #define FAST_COPY_UP(shift) \
1585     for (; j < length - 1; j += 2) { \
1586         uint32_t v = AV_RN32A(srcPtr2 + j); \
1587         AV_WN32A(dstPtr2 + j, v << shift); \
1588     }
1589 #endif
1590                              switch (shift)
1591                              {
1592                              case 6: FAST_COPY_UP(6); break;
1593                              case 7: FAST_COPY_UP(7); break;
1594                              }
1595                         }
1596 #define COPY_UP(r,w) \
1597     if(shiftonly){\
1598         for (; j < length; j++){ \
1599             unsigned int v= r(&srcPtr2[j]);\
1600             w(&dstPtr2[j], v<<(dst_depth-src_depth));\
1601         }\
1602     }else{\
1603         for (; j < length; j++){ \
1604             unsigned int v= r(&srcPtr2[j]);\
1605             w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
1606                         (v>>(2*src_depth-dst_depth)));\
1607         }\
1608     }
1609                         if(isBE(c->srcFormat)){
1610                             if(isBE(c->dstFormat)){
1611                                 COPY_UP(AV_RB16, AV_WB16)
1612                             } else {
1613                                 COPY_UP(AV_RB16, AV_WL16)
1614                             }
1615                         } else {
1616                             if(isBE(c->dstFormat)){
1617                                 COPY_UP(AV_RL16, AV_WB16)
1618                             } else {
1619                                 COPY_UP(AV_RL16, AV_WL16)
1620                             }
1621                         }
1622                         dstPtr2 += dstStride[plane]/2;
1623                         srcPtr2 += srcStride[plane]/2;
1624                     }
1625                 } else {
1626                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
1627                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
1628                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
1629                         } else {
1630                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
1631                         }
1632                     }else{
1633                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
1634                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
1635                         } else {
1636                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
1637                         }
1638                     }
1639                 }
1640             } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
1641                       isBE(c->srcFormat) != isBE(c->dstFormat)) {
1642
1643                 for (i = 0; i < height; i++) {
1644                     for (j = 0; j < length; j++)
1645                         ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
1646                     srcPtr += srcStride[plane];
1647                     dstPtr += dstStride[plane];
1648                 }
1649             } else if (dstStride[plane] == srcStride[plane] &&
1650                        srcStride[plane] > 0 && srcStride[plane] == length) {
1651                 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
1652                        height * dstStride[plane]);
1653             } else {
1654                 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
1655                     length *= 2;
1656                 else if (desc_src->comp[0].depth == 1)
1657                     length >>= 3; // monowhite/black
1658                 for (i = 0; i < height; i++) {
1659                     memcpy(dstPtr, srcPtr, length);
1660                     srcPtr += srcStride[plane];
1661                     dstPtr += dstStride[plane];
1662                 }
1663             }
1664         }
1665     }
1666     return srcSliceH;
1667 }
1668
1669
1670 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt)          \
1671     ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) ||     \
1672      (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
1673
1674
1675 void ff_get_unscaled_swscale(SwsContext *c)
1676 {
1677     const enum AVPixelFormat srcFormat = c->srcFormat;
1678     const enum AVPixelFormat dstFormat = c->dstFormat;
1679     const int flags = c->flags;
1680     const int dstH = c->dstH;
1681     int needsDither;
1682
1683     needsDither = isAnyRGB(dstFormat) &&
1684             c->dstFormatBpp < 24 &&
1685            (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
1686
1687     /* yv12_to_nv12 */
1688     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
1689         (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) {
1690         c->swscale = planarToNv12Wrapper;
1691     }
1692     /* nv12_to_yv12 */
1693     if (dstFormat == AV_PIX_FMT_YUV420P &&
1694         (srcFormat == AV_PIX_FMT_NV12 || srcFormat == AV_PIX_FMT_NV21)) {
1695         c->swscale = nv12ToPlanarWrapper;
1696     }
1697     /* yuv2bgr */
1698     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P ||
1699          srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
1700         !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) {
1701         c->swscale = ff_yuv2rgb_get_func_ptr(c);
1702     }
1703     /* yuv420p10_to_p010 */
1704     if ((srcFormat == AV_PIX_FMT_YUV420P10 || srcFormat == AV_PIX_FMT_YUVA420P10) &&
1705         dstFormat == AV_PIX_FMT_P010) {
1706         c->swscale = planarToP010Wrapper;
1707     }
1708     /* yuv420p_to_p010le */
1709     if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) &&
1710         dstFormat == AV_PIX_FMT_P010LE) {
1711         c->swscale = planar8ToP01xleWrapper;
1712     }
1713
1714     if (srcFormat == AV_PIX_FMT_YUV410P && !(dstH & 3) &&
1715         (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
1716         !(flags & SWS_BITEXACT)) {
1717         c->swscale = yvu9ToYv12Wrapper;
1718     }
1719
1720     /* bgr24toYV12 */
1721     if (srcFormat == AV_PIX_FMT_BGR24 &&
1722         (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) &&
1723         !(flags & SWS_ACCURATE_RND))
1724         c->swscale = bgr24ToYv12Wrapper;
1725
1726     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
1727     if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c)
1728         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
1729         c->swscale = rgbToRgbWrapper;
1730
1731     /* RGB to planar RGB */
1732     if ((srcFormat == AV_PIX_FMT_GBRP && dstFormat == AV_PIX_FMT_GBRAP) ||
1733         (srcFormat == AV_PIX_FMT_GBRAP && dstFormat == AV_PIX_FMT_GBRP))
1734         c->swscale = planarRgbToplanarRgbWrapper;
1735
1736 #define isByteRGB(f) (             \
1737         f == AV_PIX_FMT_RGB32   || \
1738         f == AV_PIX_FMT_RGB32_1 || \
1739         f == AV_PIX_FMT_RGB24   || \
1740         f == AV_PIX_FMT_BGR32   || \
1741         f == AV_PIX_FMT_BGR32_1 || \
1742         f == AV_PIX_FMT_BGR24)
1743
1744     if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat))
1745         c->swscale = planarRgbToRgbWrapper;
1746
1747     if ((srcFormat == AV_PIX_FMT_RGB48LE  || srcFormat == AV_PIX_FMT_RGB48BE  ||
1748          srcFormat == AV_PIX_FMT_BGR48LE  || srcFormat == AV_PIX_FMT_BGR48BE  ||
1749          srcFormat == AV_PIX_FMT_RGBA64LE || srcFormat == AV_PIX_FMT_RGBA64BE ||
1750          srcFormat == AV_PIX_FMT_BGRA64LE || srcFormat == AV_PIX_FMT_BGRA64BE) &&
1751         (dstFormat == AV_PIX_FMT_GBRP9LE  || dstFormat == AV_PIX_FMT_GBRP9BE  ||
1752          dstFormat == AV_PIX_FMT_GBRP10LE || dstFormat == AV_PIX_FMT_GBRP10BE ||
1753          dstFormat == AV_PIX_FMT_GBRP12LE || dstFormat == AV_PIX_FMT_GBRP12BE ||
1754          dstFormat == AV_PIX_FMT_GBRP14LE || dstFormat == AV_PIX_FMT_GBRP14BE ||
1755          dstFormat == AV_PIX_FMT_GBRP16LE || dstFormat == AV_PIX_FMT_GBRP16BE ||
1756          dstFormat == AV_PIX_FMT_GBRAP12LE || dstFormat == AV_PIX_FMT_GBRAP12BE ||
1757          dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE ))
1758         c->swscale = Rgb16ToPlanarRgb16Wrapper;
1759
1760     if ((srcFormat == AV_PIX_FMT_GBRP9LE  || srcFormat == AV_PIX_FMT_GBRP9BE  ||
1761          srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE ||
1762          srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE ||
1763          srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE ||
1764          srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE ||
1765          srcFormat == AV_PIX_FMT_GBRAP12LE || srcFormat == AV_PIX_FMT_GBRAP12BE ||
1766          srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) &&
1767         (dstFormat == AV_PIX_FMT_RGB48LE  || dstFormat == AV_PIX_FMT_RGB48BE  ||
1768          dstFormat == AV_PIX_FMT_BGR48LE  || dstFormat == AV_PIX_FMT_BGR48BE  ||
1769          dstFormat == AV_PIX_FMT_RGBA64LE || dstFormat == AV_PIX_FMT_RGBA64BE ||
1770          dstFormat == AV_PIX_FMT_BGRA64LE || dstFormat == AV_PIX_FMT_BGRA64BE))
1771         c->swscale = planarRgb16ToRgb16Wrapper;
1772
1773     if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth == 8 &&
1774         isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP)
1775         c->swscale = rgbToPlanarRgbWrapper;
1776
1777     if (isBayer(srcFormat)) {
1778         if (dstFormat == AV_PIX_FMT_RGB24)
1779             c->swscale = bayer_to_rgb24_wrapper;
1780         else if (dstFormat == AV_PIX_FMT_YUV420P)
1781             c->swscale = bayer_to_yv12_wrapper;
1782         else if (!isBayer(dstFormat)) {
1783             av_log(c, AV_LOG_ERROR, "unsupported bayer conversion\n");
1784             av_assert0(0);
1785         }
1786     }
1787
1788     /* bswap 16 bits per pixel/component packed formats */
1789     if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_BGGR16) ||
1790         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_RGGB16) ||
1791         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GBRG16) ||
1792         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GRBG16) ||
1793         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) ||
1794         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48)  ||
1795         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
1796         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) ||
1797         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) ||
1798         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) ||
1799         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY10) ||
1800         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY12) ||
1801         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) ||
1802         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YA16)   ||
1803         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_AYUV64) ||
1804         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP9)  ||
1805         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP10) ||
1806         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) ||
1807         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) ||
1808         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) ||
1809         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP12) ||
1810         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) ||
1811         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
1812         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48)  ||
1813         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
1814         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) ||
1815         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) ||
1816         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) ||
1817         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12)  ||
1818         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P9)  ||
1819         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P10) ||
1820         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P12) ||
1821         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P14) ||
1822         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P16) ||
1823         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P9)  ||
1824         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P10) ||
1825         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P12) ||
1826         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P14) ||
1827         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P16) ||
1828         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV440P10) ||
1829         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV440P12) ||
1830         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P9)  ||
1831         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P10) ||
1832         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P12) ||
1833         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P14) ||
1834         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16))
1835         c->swscale = packed_16bpc_bswap;
1836
1837     if (usePal(srcFormat) && isByteRGB(dstFormat))
1838         c->swscale = palToRgbWrapper;
1839
1840     if (srcFormat == AV_PIX_FMT_YUV422P) {
1841         if (dstFormat == AV_PIX_FMT_YUYV422)
1842             c->swscale = yuv422pToYuy2Wrapper;
1843         else if (dstFormat == AV_PIX_FMT_UYVY422)
1844             c->swscale = yuv422pToUyvyWrapper;
1845     }
1846
1847     /* LQ converters if -sws 0 or -sws 4*/
1848     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
1849         /* yv12_to_yuy2 */
1850         if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) {
1851             if (dstFormat == AV_PIX_FMT_YUYV422)
1852                 c->swscale = planarToYuy2Wrapper;
1853             else if (dstFormat == AV_PIX_FMT_UYVY422)
1854                 c->swscale = planarToUyvyWrapper;
1855         }
1856     }
1857     if (srcFormat == AV_PIX_FMT_YUYV422 &&
1858        (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
1859         c->swscale = yuyvToYuv420Wrapper;
1860     if (srcFormat == AV_PIX_FMT_UYVY422 &&
1861        (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P))
1862         c->swscale = uyvyToYuv420Wrapper;
1863     if (srcFormat == AV_PIX_FMT_YUYV422 && dstFormat == AV_PIX_FMT_YUV422P)
1864         c->swscale = yuyvToYuv422Wrapper;
1865     if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P)
1866         c->swscale = uyvyToYuv422Wrapper;
1867
1868 #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_YA8 && (x) != AV_PIX_FMT_YA16LE && (x) != AV_PIX_FMT_YA16BE)
1869     /* simple copy */
1870     if ( srcFormat == dstFormat ||
1871         (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) ||
1872         (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) ||
1873         (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) ||
1874         (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) ||
1875         (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) ||
1876         (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
1877          c->chrDstHSubSample == c->chrSrcHSubSample &&
1878          c->chrDstVSubSample == c->chrSrcVSubSample &&
1879          dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
1880          dstFormat != AV_PIX_FMT_P010LE && dstFormat != AV_PIX_FMT_P010BE &&
1881          dstFormat != AV_PIX_FMT_P016LE && dstFormat != AV_PIX_FMT_P016BE &&
1882          srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21 &&
1883          srcFormat != AV_PIX_FMT_P010LE && srcFormat != AV_PIX_FMT_P010BE &&
1884          srcFormat != AV_PIX_FMT_P016LE && srcFormat != AV_PIX_FMT_P016BE))
1885     {
1886         if (isPacked(c->srcFormat))
1887             c->swscale = packedCopyWrapper;
1888         else /* Planar YUV or gray */
1889             c->swscale = planarCopyWrapper;
1890     }
1891
1892     if (ARCH_PPC)
1893         ff_get_unscaled_swscale_ppc(c);
1894      if (ARCH_ARM)
1895          ff_get_unscaled_swscale_arm(c);
1896     if (ARCH_AARCH64)
1897         ff_get_unscaled_swscale_aarch64(c);
1898 }
1899
1900 /* Convert the palette to the same packed 32-bit format as the palette */
1901 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
1902                                    int num_pixels, const uint8_t *palette)
1903 {
1904     int i;
1905
1906     for (i = 0; i < num_pixels; i++)
1907         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
1908 }
1909
1910 /* Palette format: ABCD -> dst format: ABC */
1911 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
1912                                    int num_pixels, const uint8_t *palette)
1913 {
1914     int i;
1915
1916     for (i = 0; i < num_pixels; i++) {
1917         //FIXME slow?
1918         dst[0] = palette[src[i] * 4 + 0];
1919         dst[1] = palette[src[i] * 4 + 1];
1920         dst[2] = palette[src[i] * 4 + 2];
1921         dst += 3;
1922     }
1923 }