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