]> git.sesse.net Git - ffmpeg/blob - libswscale/swscale_unscaled.c
swscale: Fix packed rgb check for planarRgbToRgbWrapper.
[ffmpeg] / libswscale / swscale_unscaled.c
1 /*
2  * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <inttypes.h>
22 #include <string.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include "config.h"
26 #include <assert.h>
27 #include "swscale.h"
28 #include "swscale_internal.h"
29 #include "rgb2rgb.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/cpu.h"
32 #include "libavutil/avutil.h"
33 #include "libavutil/mathematics.h"
34 #include "libavutil/bswap.h"
35 #include "libavutil/pixdesc.h"
36
37 #define RGB2YUV_SHIFT 15
38 #define BY ( (int)(0.114*219/255*(1<<RGB2YUV_SHIFT)+0.5))
39 #define BV (-(int)(0.081*224/255*(1<<RGB2YUV_SHIFT)+0.5))
40 #define BU ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
41 #define GY ( (int)(0.587*219/255*(1<<RGB2YUV_SHIFT)+0.5))
42 #define GV (-(int)(0.419*224/255*(1<<RGB2YUV_SHIFT)+0.5))
43 #define GU (-(int)(0.331*224/255*(1<<RGB2YUV_SHIFT)+0.5))
44 #define RY ( (int)(0.299*219/255*(1<<RGB2YUV_SHIFT)+0.5))
45 #define RV ( (int)(0.500*224/255*(1<<RGB2YUV_SHIFT)+0.5))
46 #define RU (-(int)(0.169*224/255*(1<<RGB2YUV_SHIFT)+0.5))
47
48 static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val)
49 {
50     int i;
51     uint8_t *ptr = plane + stride*y;
52     for (i=0; i<height; i++) {
53         memset(ptr, val, width);
54         ptr += stride;
55     }
56 }
57
58 static void copyPlane(const uint8_t *src, int srcStride,
59                       int srcSliceY, int srcSliceH, int width,
60                       uint8_t *dst, int dstStride)
61 {
62     dst += dstStride * srcSliceY;
63     if (dstStride == srcStride && srcStride > 0) {
64         memcpy(dst, src, srcSliceH * dstStride);
65     } else {
66         int i;
67         for (i=0; i<srcSliceH; i++) {
68             memcpy(dst, src, width);
69             src += srcStride;
70             dst += dstStride;
71         }
72     }
73 }
74
75 static int planarToNv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
76                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
77 {
78     uint8_t *dst = dstParam[1] + dstStride[1]*srcSliceY/2;
79
80     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
81               dstParam[0], dstStride[0]);
82
83     if (c->dstFormat == PIX_FMT_NV12)
84         interleaveBytes(src[1], src[2], dst, c->srcW/2, srcSliceH/2, srcStride[1], srcStride[2], dstStride[0]);
85     else
86         interleaveBytes(src[2], src[1], dst, c->srcW/2, srcSliceH/2, srcStride[2], srcStride[1], dstStride[0]);
87
88     return srcSliceH;
89 }
90
91 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
92                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
93 {
94     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
95
96     yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
97
98     return srcSliceH;
99 }
100
101 static int planarToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
102                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
103 {
104     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
105
106     yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], srcStride[1], dstStride[0]);
107
108     return srcSliceH;
109 }
110
111 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
112                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
113 {
114     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
115
116     yuv422ptoyuy2(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
117
118     return srcSliceH;
119 }
120
121 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
122                                 int srcSliceH, uint8_t* dstParam[], int dstStride[])
123 {
124     uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
125
126     yuv422ptouyvy(src[0],src[1],src[2],dst,c->srcW,srcSliceH,srcStride[0],srcStride[1],dstStride[0]);
127
128     return srcSliceH;
129 }
130
131 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
132                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
133 {
134     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
135     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
136     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
137
138     yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
139
140     if (dstParam[3])
141         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
142
143     return srcSliceH;
144 }
145
146 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
147                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
148 {
149     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
150     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
151     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
152
153     yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
154
155     return srcSliceH;
156 }
157
158 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
159                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
160 {
161     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
162     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
163     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
164
165     uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
166
167     if (dstParam[3])
168         fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
169
170     return srcSliceH;
171 }
172
173 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
174                                int srcSliceH, uint8_t* dstParam[], int dstStride[])
175 {
176     uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
177     uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
178     uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
179
180     uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
181
182     return srcSliceH;
183 }
184
185 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
186 {
187     int i;
188     for (i=0; i<num_pixels; i++)
189         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | (src[(i<<1)+1] << 24);
190 }
191
192 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
193 {
194     int i;
195
196     for (i=0; i<num_pixels; i++)
197         ((uint32_t *) dst)[i] = ((const uint32_t *)palette)[src[i<<1]] | src[(i<<1)+1];
198 }
199
200 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
201 {
202     int i;
203
204     for (i=0; i<num_pixels; i++) {
205         //FIXME slow?
206         dst[0]= palette[src[i<<1]*4+0];
207         dst[1]= palette[src[i<<1]*4+1];
208         dst[2]= palette[src[i<<1]*4+2];
209         dst+= 3;
210     }
211 }
212
213 static int palToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
214                            int srcSliceH, uint8_t* dst[], int dstStride[])
215 {
216     const enum PixelFormat srcFormat= c->srcFormat;
217     const enum PixelFormat dstFormat= c->dstFormat;
218     void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
219                  const uint8_t *palette)=NULL;
220     int i;
221     uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
222     const uint8_t *srcPtr= src[0];
223
224     if (srcFormat == PIX_FMT_GRAY8A) {
225         switch (dstFormat) {
226         case PIX_FMT_RGB32  : conv = gray8aToPacked32; break;
227         case PIX_FMT_BGR32  : conv = gray8aToPacked32; break;
228         case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
229         case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
230         case PIX_FMT_RGB24  : conv = gray8aToPacked24; break;
231         case PIX_FMT_BGR24  : conv = gray8aToPacked24; break;
232         }
233     } else if (usePal(srcFormat)) {
234         switch (dstFormat) {
235         case PIX_FMT_RGB32  : conv = sws_convertPalette8ToPacked32; break;
236         case PIX_FMT_BGR32  : conv = sws_convertPalette8ToPacked32; break;
237         case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
238         case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
239         case PIX_FMT_RGB24  : conv = sws_convertPalette8ToPacked24; break;
240         case PIX_FMT_BGR24  : conv = sws_convertPalette8ToPacked24; break;
241         }
242     }
243
244     if (!conv)
245         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
246                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
247     else {
248         for (i=0; i<srcSliceH; i++) {
249             conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
250             srcPtr+= srcStride[0];
251             dstPtr+= dstStride[0];
252         }
253     }
254
255     return srcSliceH;
256 }
257
258 static void gbr24ptopacked24(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int width)
259 {
260     int x, h, i;
261     for (h = 0; h < srcSliceH; h++) {
262         uint8_t *dest = dst + dstStride * h;
263         for (x = 0; x < width; x++) {
264             *dest++ = src[0][x];
265             *dest++ = src[1][x];
266             *dest++ = src[2][x];
267         }
268
269         for (i = 0; i < 3; i++)
270             src[i] += srcStride[i];
271     }
272 }
273
274 static void gbr24ptopacked32(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int alpha_first, int width)
275 {
276     int x, h, i;
277     for (h = 0; h < srcSliceH; h++) {
278         uint8_t *dest = dst + dstStride * h;
279
280         if (alpha_first) {
281             for (x = 0; x < width; x++) {
282                 *dest++ = 0xff;
283                 *dest++ = src[0][x];
284                 *dest++ = src[1][x];
285                 *dest++ = src[2][x];
286             }
287         } else {
288             for (x = 0; x < width; x++) {
289                 *dest++ = src[0][x];
290                 *dest++ = src[1][x];
291                 *dest++ = src[2][x];
292                 *dest++ = 0xff;
293             }
294         }
295
296         for (i = 0; i < 3; i++)
297             src[i] += srcStride[i];
298     }
299 }
300
301 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
302         int srcSliceH, uint8_t* dst[], int dstStride[])
303 {
304     int alpha_first = 0;
305     if (c->srcFormat != PIX_FMT_GBR24P) {
306         av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
307               av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
308         return srcSliceH;
309     }
310
311     switch (c->dstFormat) {
312         case PIX_FMT_BGR24:
313             gbr24ptopacked24((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
314                   dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
315             break;
316
317         case PIX_FMT_RGB24:
318             gbr24ptopacked24((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
319                   dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
320             break;
321
322         case PIX_FMT_ARGB:
323             alpha_first = 1;
324         case PIX_FMT_RGBA:
325             gbr24ptopacked32((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
326                   dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
327             break;
328
329         case PIX_FMT_ABGR:
330             alpha_first = 1;
331         case PIX_FMT_BGRA:
332             gbr24ptopacked32((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
333                   dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
334             break;
335
336         default:
337             av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
338                     av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
339     }
340
341     return srcSliceH;
342 }
343
344 #define isRGBA32(x) (            \
345            (x) == PIX_FMT_ARGB   \
346         || (x) == PIX_FMT_RGBA   \
347         || (x) == PIX_FMT_BGRA   \
348         || (x) == PIX_FMT_ABGR   \
349         )
350
351 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
352 static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
353                            int srcSliceH, uint8_t* dst[], int dstStride[])
354 {
355     const enum PixelFormat srcFormat= c->srcFormat;
356     const enum PixelFormat dstFormat= c->dstFormat;
357     const int srcBpp= (c->srcFormatBpp + 7) >> 3;
358     const int dstBpp= (c->dstFormatBpp + 7) >> 3;
359     const int srcId= c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
360     const int dstId= c->dstFormatBpp >> 2;
361     void (*conv)(const uint8_t *src, uint8_t *dst, int src_size)=NULL;
362
363 #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
364
365     if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
366         if (     CONV_IS(ABGR, RGBA)
367               || CONV_IS(ARGB, BGRA)
368               || CONV_IS(BGRA, ARGB)
369               || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
370         else if (CONV_IS(ABGR, ARGB)
371               || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
372         else if (CONV_IS(ABGR, BGRA)
373               || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
374         else if (CONV_IS(BGRA, RGBA)
375               || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
376         else if (CONV_IS(BGRA, ABGR)
377               || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
378     } else
379     /* BGR -> BGR */
380     if (  (isBGRinInt(srcFormat) && isBGRinInt(dstFormat))
381        || (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
382         switch(srcId | (dstId<<4)) {
383         case 0x34: conv= rgb16to15; break;
384         case 0x36: conv= rgb24to15; break;
385         case 0x38: conv= rgb32to15; break;
386         case 0x43: conv= rgb15to16; break;
387         case 0x46: conv= rgb24to16; break;
388         case 0x48: conv= rgb32to16; break;
389         case 0x63: conv= rgb15to24; break;
390         case 0x64: conv= rgb16to24; break;
391         case 0x68: conv= rgb32to24; break;
392         case 0x83: conv= rgb15to32; break;
393         case 0x84: conv= rgb16to32; break;
394         case 0x86: conv= rgb24to32; break;
395         }
396     } else if (  (isBGRinInt(srcFormat) && isRGBinInt(dstFormat))
397              || (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
398         switch(srcId | (dstId<<4)) {
399         case 0x33: conv= rgb15tobgr15; break;
400         case 0x34: conv= rgb16tobgr15; break;
401         case 0x36: conv= rgb24tobgr15; break;
402         case 0x38: conv= rgb32tobgr15; break;
403         case 0x43: conv= rgb15tobgr16; break;
404         case 0x44: conv= rgb16tobgr16; break;
405         case 0x46: conv= rgb24tobgr16; break;
406         case 0x48: conv= rgb32tobgr16; break;
407         case 0x63: conv= rgb15tobgr24; break;
408         case 0x64: conv= rgb16tobgr24; break;
409         case 0x66: conv= rgb24tobgr24; break;
410         case 0x68: conv= rgb32tobgr24; break;
411         case 0x83: conv= rgb15tobgr32; break;
412         case 0x84: conv= rgb16tobgr32; break;
413         case 0x86: conv= rgb24tobgr32; break;
414         }
415     }
416
417     if (!conv) {
418         av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
419                av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
420     } else {
421         const uint8_t *srcPtr= src[0];
422               uint8_t *dstPtr= dst[0];
423         if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) && !isRGBA32(dstFormat))
424             srcPtr += ALT32_CORR;
425
426         if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat))
427             dstPtr += ALT32_CORR;
428
429         if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0 && !(srcStride[0] % srcBpp))
430             conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]);
431         else {
432             int i;
433             dstPtr += dstStride[0]*srcSliceY;
434
435             for (i=0; i<srcSliceH; i++) {
436                 conv(srcPtr, dstPtr, c->srcW*srcBpp);
437                 srcPtr+= srcStride[0];
438                 dstPtr+= dstStride[0];
439             }
440         }
441     }
442     return srcSliceH;
443 }
444
445 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
446                               int srcSliceH, uint8_t* dst[], int dstStride[])
447 {
448     rgb24toyv12(
449         src[0],
450         dst[0]+ srcSliceY    *dstStride[0],
451         dst[1]+(srcSliceY>>1)*dstStride[1],
452         dst[2]+(srcSliceY>>1)*dstStride[2],
453         c->srcW, srcSliceH,
454         dstStride[0], dstStride[1], srcStride[0]);
455     if (dst[3])
456         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
457     return srcSliceH;
458 }
459
460 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
461                              int srcSliceH, uint8_t* dst[], int dstStride[])
462 {
463     copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
464               dst[0], dstStride[0]);
465
466     planar2x(src[1], dst[1] + dstStride[1]*(srcSliceY >> 1), c->chrSrcW,
467              srcSliceH >> 2, srcStride[1], dstStride[1]);
468     planar2x(src[2], dst[2] + dstStride[2]*(srcSliceY >> 1), c->chrSrcW,
469              srcSliceH >> 2, srcStride[2], dstStride[2]);
470     if (dst[3])
471         fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
472     return srcSliceH;
473 }
474
475 /* unscaled copy like stuff (assumes nearly identical formats) */
476 static int packedCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
477                              int srcSliceH, uint8_t* dst[], int dstStride[])
478 {
479     if (dstStride[0]==srcStride[0] && srcStride[0] > 0)
480         memcpy(dst[0] + dstStride[0]*srcSliceY, src[0], srcSliceH*dstStride[0]);
481     else {
482         int i;
483         const uint8_t *srcPtr= src[0];
484         uint8_t *dstPtr= dst[0] + dstStride[0]*srcSliceY;
485         int length=0;
486
487         /* universal length finder */
488         while(length+c->srcW <= FFABS(dstStride[0])
489            && length+c->srcW <= FFABS(srcStride[0])) length+= c->srcW;
490         assert(length!=0);
491
492         for (i=0; i<srcSliceH; i++) {
493             memcpy(dstPtr, srcPtr, length);
494             srcPtr+= srcStride[0];
495             dstPtr+= dstStride[0];
496         }
497     }
498     return srcSliceH;
499 }
500
501 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
502     uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
503     int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
504     for (i = 0; i < height; i++) {\
505         const uint8_t *dither= dithers[src_depth-9][i&7];\
506         for (j = 0; j < length-7; j+=8){\
507             dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
508             dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
509             dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
510             dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
511             dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
512             dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
513             dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
514             dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
515         }\
516         for (; j < length; j++)\
517             dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
518         dst += dstStride;\
519         src += srcStride;\
520     }
521
522
523 static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
524                              int srcSliceH, uint8_t* dst[], int dstStride[])
525 {
526     int plane, i, j;
527     for (plane=0; plane<4; plane++) {
528         int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
529         int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
530         int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
531         const uint8_t *srcPtr= src[plane];
532         uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
533         int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
534
535         if (!dst[plane]) continue;
536         // ignore palette for GRAY8
537         if (plane == 1 && !dst[2]) continue;
538         if (!src[plane] || (plane == 1 && !src[2])) {
539             if(is16BPS(c->dstFormat))
540                 length*=2;
541             fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
542         } else {
543             if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
544                || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
545             ) {
546                 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
547                 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1+1;
548                 const uint16_t *srcPtr2 = (const uint16_t*)srcPtr;
549                 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
550
551                 if (dst_depth == 8) {
552                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
553                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
554                     } else {
555                         DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
556                     }
557                 } else if (src_depth == 8) {
558                     for (i = 0; i < height; i++) {
559                         #define COPY816(w)\
560                         if(shiftonly){\
561                             for (j = 0; j < length; j++)\
562                                 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
563                         }else{\
564                             for (j = 0; j < length; j++)\
565                                 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
566                                                (srcPtr[j]>>(2*8-dst_depth)));\
567                         }
568                         if(isBE(c->dstFormat)){
569                             COPY816(AV_WB16)
570                         } else {
571                             COPY816(AV_WL16)
572                         }
573                         dstPtr2 += dstStride[plane]/2;
574                         srcPtr  += srcStride[plane];
575                     }
576                 } else if (src_depth <= dst_depth) {
577                     for (i = 0; i < height; i++) {
578 #define COPY_UP(r,w) \
579     if(shiftonly){\
580         for (j = 0; j < length; j++){ \
581             unsigned int v= r(&srcPtr2[j]);\
582             w(&dstPtr2[j], v<<(dst_depth-src_depth));\
583         }\
584     }else{\
585         for (j = 0; j < length; j++){ \
586             unsigned int v= r(&srcPtr2[j]);\
587             w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
588                         (v>>(2*src_depth-dst_depth)));\
589         }\
590     }
591                         if(isBE(c->srcFormat)){
592                             if(isBE(c->dstFormat)){
593                                 COPY_UP(AV_RB16, AV_WB16)
594                             } else {
595                                 COPY_UP(AV_RB16, AV_WL16)
596                             }
597                         } else {
598                             if(isBE(c->dstFormat)){
599                                 COPY_UP(AV_RL16, AV_WB16)
600                             } else {
601                                 COPY_UP(AV_RL16, AV_WL16)
602                             }
603                         }
604                         dstPtr2 += dstStride[plane]/2;
605                         srcPtr2 += srcStride[plane]/2;
606                     }
607                 } else {
608                     if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
609                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
610                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
611                         } else {
612                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
613                         }
614                     }else{
615                         if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
616                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
617                         } else {
618                             DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
619                         }
620                     }
621                 }
622             } else if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat)
623                   && isBE(c->srcFormat) != isBE(c->dstFormat)) {
624
625                 for (i=0; i<height; i++) {
626                     for (j=0; j<length; j++)
627                         ((uint16_t*)dstPtr)[j] = av_bswap16(((const uint16_t*)srcPtr)[j]);
628                     srcPtr+= srcStride[plane];
629                     dstPtr+= dstStride[plane];
630                 }
631             } else if (dstStride[plane] == srcStride[plane] &&
632                        srcStride[plane] > 0 && srcStride[plane] == length) {
633                 memcpy(dst[plane] + dstStride[plane]*y, src[plane],
634                        height*dstStride[plane]);
635             } else {
636                 if(is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
637                     length*=2;
638                 for (i=0; i<height; i++) {
639                     memcpy(dstPtr, srcPtr, length);
640                     srcPtr+= srcStride[plane];
641                     dstPtr+= dstStride[plane];
642                 }
643             }
644         }
645     }
646     return srcSliceH;
647 }
648
649 void ff_get_unscaled_swscale(SwsContext *c)
650 {
651     const enum PixelFormat srcFormat = c->srcFormat;
652     const enum PixelFormat dstFormat = c->dstFormat;
653     const int flags = c->flags;
654     const int dstH = c->dstH;
655     int needsDither;
656
657     needsDither= isAnyRGB(dstFormat)
658         &&  c->dstFormatBpp < 24
659         && (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
660
661     /* yv12_to_nv12 */
662     if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) && (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
663         c->swScale= planarToNv12Wrapper;
664     }
665     /* yuv2bgr */
666     if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && isAnyRGB(dstFormat)
667         && !(flags & SWS_ACCURATE_RND) && !(dstH&1)) {
668         c->swScale= ff_yuv2rgb_get_func_ptr(c);
669     }
670
671     if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT)) {
672         c->swScale= yvu9ToYv12Wrapper;
673     }
674
675     /* bgr24toYV12 */
676     if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
677         c->swScale= bgr24ToYv12Wrapper;
678
679     /* RGB/BGR -> RGB/BGR (no dither needed forms) */
680     if (   isAnyRGB(srcFormat)
681         && isAnyRGB(dstFormat)
682         && srcFormat != PIX_FMT_BGR8      && dstFormat != PIX_FMT_BGR8
683         && srcFormat != PIX_FMT_RGB8      && dstFormat != PIX_FMT_RGB8
684         && srcFormat != PIX_FMT_BGR4      && dstFormat != PIX_FMT_BGR4
685         && srcFormat != PIX_FMT_RGB4      && dstFormat != PIX_FMT_RGB4
686         && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
687         && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
688         && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
689         && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
690         && srcFormat != PIX_FMT_RGB48LE   && dstFormat != PIX_FMT_RGB48LE
691         && srcFormat != PIX_FMT_RGB48BE   && dstFormat != PIX_FMT_RGB48BE
692         && srcFormat != PIX_FMT_BGR48LE   && dstFormat != PIX_FMT_BGR48LE
693         && srcFormat != PIX_FMT_BGR48BE   && dstFormat != PIX_FMT_BGR48BE
694         && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
695         c->swScale= rgbToRgbWrapper;
696
697 #define isByteRGB(f) (\
698         f == PIX_FMT_RGB32   ||\
699         f == PIX_FMT_RGB32_1 ||\
700         f == PIX_FMT_RGB24   ||\
701         f == PIX_FMT_BGR32   ||\
702         f == PIX_FMT_BGR32_1 ||\
703         f == PIX_FMT_BGR24)
704
705     if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
706         c->swScale= planarRgbToRgbWrapper;
707
708     if ((usePal(srcFormat) && (
709         dstFormat == PIX_FMT_RGB32   ||
710         dstFormat == PIX_FMT_RGB32_1 ||
711         dstFormat == PIX_FMT_RGB24   ||
712         dstFormat == PIX_FMT_BGR32   ||
713         dstFormat == PIX_FMT_BGR32_1 ||
714         dstFormat == PIX_FMT_BGR24)))
715         c->swScale= palToRgbWrapper;
716
717     if (srcFormat == PIX_FMT_YUV422P) {
718         if (dstFormat == PIX_FMT_YUYV422)
719             c->swScale= yuv422pToYuy2Wrapper;
720         else if (dstFormat == PIX_FMT_UYVY422)
721             c->swScale= yuv422pToUyvyWrapper;
722     }
723
724     /* LQ converters if -sws 0 or -sws 4*/
725     if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
726         /* yv12_to_yuy2 */
727         if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
728             if (dstFormat == PIX_FMT_YUYV422)
729                 c->swScale= planarToYuy2Wrapper;
730             else if (dstFormat == PIX_FMT_UYVY422)
731                 c->swScale= planarToUyvyWrapper;
732         }
733     }
734     if(srcFormat == PIX_FMT_YUYV422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
735         c->swScale= yuyvToYuv420Wrapper;
736     if(srcFormat == PIX_FMT_UYVY422 && (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
737         c->swScale= uyvyToYuv420Wrapper;
738     if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
739         c->swScale= yuyvToYuv422Wrapper;
740     if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
741         c->swScale= uyvyToYuv422Wrapper;
742
743     /* simple copy */
744     if (  srcFormat == dstFormat
745         || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
746         || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
747         || (isPlanarYUV(srcFormat) && isGray(dstFormat))
748         || (isPlanarYUV(dstFormat) && isGray(srcFormat))
749         || (isGray(dstFormat) && isGray(srcFormat))
750         || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)
751             && c->chrDstHSubSample == c->chrSrcHSubSample
752             && c->chrDstVSubSample == c->chrSrcVSubSample
753             && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21
754             && srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
755     {
756         if (isPacked(c->srcFormat))
757             c->swScale= packedCopyWrapper;
758         else /* Planar YUV or gray */
759             c->swScale= planarCopyWrapper;
760     }
761
762     if (ARCH_BFIN)
763         ff_bfin_get_unscaled_swscale(c);
764     if (HAVE_ALTIVEC)
765         ff_swscale_get_unscaled_altivec(c);
766 }
767
768 static void reset_ptr(const uint8_t* src[], int format)
769 {
770     if(!isALPHA(format))
771         src[3]=NULL;
772     if(!isPlanar(format)) {
773         src[3]=src[2]=NULL;
774
775         if (!usePal(format))
776             src[1]= NULL;
777     }
778 }
779
780 static int check_image_pointers(uint8_t *data[4], enum PixelFormat pix_fmt,
781                                 const int linesizes[4])
782 {
783     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
784     int i;
785
786     for (i = 0; i < 4; i++) {
787         int plane = desc->comp[i].plane;
788         if (!data[plane] || !linesizes[plane])
789             return 0;
790     }
791
792     return 1;
793 }
794
795 /**
796  * swscale wrapper, so we don't need to export the SwsContext.
797  * Assumes planar YUV to be in YUV order instead of YVU.
798  */
799 int sws_scale(struct SwsContext *c, const uint8_t* const srcSlice[],
800               const int srcStride[], int srcSliceY, int srcSliceH,
801               uint8_t* const dst[], const int dstStride[])
802 {
803     int i;
804     const uint8_t* src2[4]= {srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3]};
805     uint8_t* dst2[4]= {dst[0], dst[1], dst[2], dst[3]};
806
807     // do not mess up sliceDir if we have a "trailing" 0-size slice
808     if (srcSliceH == 0)
809         return 0;
810
811     if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
812         av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
813         return 0;
814     }
815     if (!check_image_pointers(dst, c->dstFormat, dstStride)) {
816         av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
817         return 0;
818     }
819
820     if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
821         av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
822         return 0;
823     }
824     if (c->sliceDir == 0) {
825         if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
826     }
827
828     if (usePal(c->srcFormat)) {
829         for (i=0; i<256; i++) {
830             int p, r, g, b, y, u, v, a = 0xff;
831             if(c->srcFormat == PIX_FMT_PAL8) {
832                 p=((const uint32_t*)(srcSlice[1]))[i];
833                 a= (p>>24)&0xFF;
834                 r= (p>>16)&0xFF;
835                 g= (p>> 8)&0xFF;
836                 b=  p     &0xFF;
837             } else if(c->srcFormat == PIX_FMT_RGB8) {
838                 r= (i>>5    )*36;
839                 g= ((i>>2)&7)*36;
840                 b= (i&3     )*85;
841             } else if(c->srcFormat == PIX_FMT_BGR8) {
842                 b= (i>>6    )*85;
843                 g= ((i>>3)&7)*36;
844                 r= (i&7     )*36;
845             } else if(c->srcFormat == PIX_FMT_RGB4_BYTE) {
846                 r= (i>>3    )*255;
847                 g= ((i>>1)&3)*85;
848                 b= (i&1     )*255;
849             } else if(c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
850                 r = g = b = i;
851             } else {
852                 assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
853                 b= (i>>3    )*255;
854                 g= ((i>>1)&3)*85;
855                 r= (i&1     )*255;
856             }
857             y= av_clip_uint8((RY*r + GY*g + BY*b + ( 33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
858             u= av_clip_uint8((RU*r + GU*g + BU*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
859             v= av_clip_uint8((RV*r + GV*g + BV*b + (257<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);
860             c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
861
862             switch(c->dstFormat) {
863             case PIX_FMT_BGR32:
864 #if !HAVE_BIGENDIAN
865             case PIX_FMT_RGB24:
866 #endif
867                 c->pal_rgb[i]=  r + (g<<8) + (b<<16) + (a<<24);
868                 break;
869             case PIX_FMT_BGR32_1:
870 #if HAVE_BIGENDIAN
871             case PIX_FMT_BGR24:
872 #endif
873                 c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
874                 break;
875             case PIX_FMT_RGB32_1:
876 #if HAVE_BIGENDIAN
877             case PIX_FMT_RGB24:
878 #endif
879                 c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
880                 break;
881             case PIX_FMT_RGB32:
882 #if !HAVE_BIGENDIAN
883             case PIX_FMT_BGR24:
884 #endif
885             default:
886                 c->pal_rgb[i]=  b + (g<<8) + (r<<16) + (a<<24);
887             }
888         }
889     }
890
891     // copy strides, so they can safely be modified
892     if (c->sliceDir == 1) {
893         // slices go from top to bottom
894         int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
895         int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
896
897         reset_ptr(src2, c->srcFormat);
898         reset_ptr((void*)dst2, c->dstFormat);
899
900         /* reset slice direction at end of frame */
901         if (srcSliceY + srcSliceH == c->srcH)
902             c->sliceDir = 0;
903
904         return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, dstStride2);
905     } else {
906         // slices go from bottom to top => we flip the image internally
907         int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
908         int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
909
910         src2[0] += (srcSliceH-1)*srcStride[0];
911         if (!usePal(c->srcFormat))
912             src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
913         src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
914         src2[3] += (srcSliceH-1)*srcStride[3];
915         dst2[0] += ( c->dstH                      -1)*dstStride[0];
916         dst2[1] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1];
917         dst2[2] += ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2];
918         dst2[3] += ( c->dstH                      -1)*dstStride[3];
919
920         reset_ptr(src2, c->srcFormat);
921         reset_ptr((const uint8_t**)dst2, c->dstFormat);
922
923         /* reset slice direction at end of frame */
924         if (!srcSliceY)
925             c->sliceDir = 0;
926
927         return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
928     }
929 }
930
931 /* Convert the palette to the same packed 32-bit format as the palette */
932 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
933 {
934     int i;
935
936     for (i=0; i<num_pixels; i++)
937         ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
938 }
939
940 /* Palette format: ABCD -> dst format: ABC */
941 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette)
942 {
943     int i;
944
945     for (i=0; i<num_pixels; i++) {
946         //FIXME slow?
947         dst[0]= palette[src[i]*4+0];
948         dst[1]= palette[src[i]*4+1];
949         dst[2]= palette[src[i]*4+2];
950         dst+= 3;
951     }
952 }