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