2 * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
4 * This file is part of FFmpeg.
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.
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.
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
28 #include "swscale_internal.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"
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))
48 static void fillPlane(uint8_t *plane, int stride, int width, int height, int y,
52 uint8_t *ptr = plane + stride * y;
53 for (i = 0; i < height; i++) {
54 memset(ptr, val, width);
59 static void copyPlane(const uint8_t *src, int srcStride,
60 int srcSliceY, int srcSliceH, int width,
61 uint8_t *dst, int dstStride)
63 dst += dstStride * srcSliceY;
64 if (dstStride == srcStride && srcStride > 0) {
65 memcpy(dst, src, srcSliceH * dstStride);
68 for (i = 0; i < srcSliceH; i++) {
69 memcpy(dst, src, width);
76 static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[],
77 int srcStride[], int srcSliceY,
78 int srcSliceH, uint8_t *dstParam[],
81 uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2;
83 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
84 dstParam[0], dstStride[0]);
86 if (c->dstFormat == PIX_FMT_NV12)
87 interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2,
88 srcStride[1], srcStride[2], dstStride[0]);
90 interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2,
91 srcStride[2], srcStride[1], dstStride[0]);
96 static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
97 int srcStride[], int srcSliceY, int srcSliceH,
98 uint8_t *dstParam[], int dstStride[])
100 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
102 yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
103 srcStride[1], dstStride[0]);
108 static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[],
109 int srcStride[], int srcSliceY, int srcSliceH,
110 uint8_t *dstParam[], int dstStride[])
112 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
114 yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
115 srcStride[1], dstStride[0]);
120 static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[],
121 int srcStride[], int srcSliceY, int srcSliceH,
122 uint8_t *dstParam[], int dstStride[])
124 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
126 yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
127 srcStride[1], dstStride[0]);
132 static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[],
133 int srcStride[], int srcSliceY, int srcSliceH,
134 uint8_t *dstParam[], int dstStride[])
136 uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY;
138 yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0],
139 srcStride[1], dstStride[0]);
144 static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
145 int srcStride[], int srcSliceY, int srcSliceH,
146 uint8_t *dstParam[], int dstStride[])
148 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
149 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
150 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
152 yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
153 dstStride[1], srcStride[0]);
156 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
161 static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
162 int srcStride[], int srcSliceY, int srcSliceH,
163 uint8_t *dstParam[], int dstStride[])
165 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
166 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
167 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
169 yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
170 dstStride[1], srcStride[0]);
175 static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[],
176 int srcStride[], int srcSliceY, int srcSliceH,
177 uint8_t *dstParam[], int dstStride[])
179 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
180 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2;
181 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2;
183 uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
184 dstStride[1], srcStride[0]);
187 fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
192 static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[],
193 int srcStride[], int srcSliceY, int srcSliceH,
194 uint8_t *dstParam[], int dstStride[])
196 uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY;
197 uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY;
198 uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY;
200 uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0],
201 dstStride[1], srcStride[0]);
206 static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels,
207 const uint8_t *palette)
210 for (i = 0; i < num_pixels; i++)
211 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24);
214 static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels,
215 const uint8_t *palette)
219 for (i = 0; i < num_pixels; i++)
220 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1];
223 static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels,
224 const uint8_t *palette)
228 for (i = 0; i < num_pixels; i++) {
230 dst[0] = palette[src[i << 1] * 4 + 0];
231 dst[1] = palette[src[i << 1] * 4 + 1];
232 dst[2] = palette[src[i << 1] * 4 + 2];
237 static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[],
238 int srcStride[], int srcSliceY, int srcSliceH,
239 uint8_t *dst[], int dstStride[])
242 int srcstr = srcStride[0] >> 1;
243 int dststr = dstStride[0] >> 1;
244 uint16_t *dstPtr = (uint16_t *) dst[0];
245 const uint16_t *srcPtr = (const uint16_t *) src[0];
246 int min_stride = FFMIN(srcstr, dststr);
248 for (i = 0; i < srcSliceH; i++) {
249 for (j = 0; j < min_stride; j++) {
250 dstPtr[j] = av_bswap16(srcPtr[j]);
259 static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
260 int srcSliceY, int srcSliceH, uint8_t *dst[],
263 const enum PixelFormat srcFormat = c->srcFormat;
264 const enum PixelFormat dstFormat = c->dstFormat;
265 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
266 const uint8_t *palette) = NULL;
268 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
269 const uint8_t *srcPtr = src[0];
271 if (srcFormat == PIX_FMT_GRAY8A) {
273 case PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
274 case PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
275 case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
276 case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
277 case PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
278 case PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
280 } else if (usePal(srcFormat)) {
282 case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
283 case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
284 case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
285 case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
286 case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break;
287 case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break;
292 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
293 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
295 for (i = 0; i < srcSliceH; i++) {
296 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
297 srcPtr += srcStride[0];
298 dstPtr += dstStride[0];
305 static void gbr24ptopacked24(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int width)
308 for (h = 0; h < srcSliceH; h++) {
309 uint8_t *dest = dst + dstStride * h;
310 for (x = 0; x < width; x++) {
316 for (i = 0; i < 3; i++)
317 src[i] += srcStride[i];
321 static void gbr24ptopacked32(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int alpha_first, int width)
324 for (h = 0; h < srcSliceH; h++) {
325 uint8_t *dest = dst + dstStride * h;
328 for (x = 0; x < width; x++) {
335 for (x = 0; x < width; x++) {
343 for (i = 0; i < 3; i++)
344 src[i] += srcStride[i];
348 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
349 int srcSliceH, uint8_t* dst[], int dstStride[])
352 if (c->srcFormat != PIX_FMT_GBR24P) {
353 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
354 av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
358 switch (c->dstFormat) {
360 gbr24ptopacked24((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
361 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
365 gbr24ptopacked24((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
366 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
372 gbr24ptopacked32((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
373 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
379 gbr24ptopacked32((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
380 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
384 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
385 av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
391 #define isRGBA32(x) ( \
392 (x) == PIX_FMT_ARGB \
393 || (x) == PIX_FMT_RGBA \
394 || (x) == PIX_FMT_BGRA \
395 || (x) == PIX_FMT_ABGR \
398 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
399 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
400 int srcSliceY, int srcSliceH, uint8_t *dst[],
403 const enum PixelFormat srcFormat = c->srcFormat;
404 const enum PixelFormat dstFormat = c->dstFormat;
405 const int srcBpp = (c->srcFormatBpp + 7) >> 3;
406 const int dstBpp = (c->dstFormatBpp + 7) >> 3;
407 const int srcId = c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
408 const int dstId = c->dstFormatBpp >> 2;
409 void (*conv)(const uint8_t *src, uint8_t *dst, int src_size) = NULL;
411 #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
413 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
414 if ( CONV_IS(ABGR, RGBA)
415 || CONV_IS(ARGB, BGRA)
416 || CONV_IS(BGRA, ARGB)
417 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
418 else if (CONV_IS(ABGR, ARGB)
419 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
420 else if (CONV_IS(ABGR, BGRA)
421 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
422 else if (CONV_IS(BGRA, RGBA)
423 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
424 else if (CONV_IS(BGRA, ABGR)
425 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
428 if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
429 (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
430 switch (srcId | (dstId << 4)) {
431 case 0x34: conv = rgb16to15; break;
432 case 0x36: conv = rgb24to15; break;
433 case 0x38: conv = rgb32to15; break;
434 case 0x43: conv = rgb15to16; break;
435 case 0x46: conv = rgb24to16; break;
436 case 0x48: conv = rgb32to16; break;
437 case 0x63: conv = rgb15to24; break;
438 case 0x64: conv = rgb16to24; break;
439 case 0x68: conv = rgb32to24; break;
440 case 0x83: conv = rgb15to32; break;
441 case 0x84: conv = rgb16to32; break;
442 case 0x86: conv = rgb24to32; break;
444 } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
445 (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
446 switch (srcId | (dstId << 4)) {
447 case 0x33: conv = rgb15tobgr15; break;
448 case 0x34: conv = rgb16tobgr15; break;
449 case 0x36: conv = rgb24tobgr15; break;
450 case 0x38: conv = rgb32tobgr15; break;
451 case 0x43: conv = rgb15tobgr16; break;
452 case 0x44: conv = rgb16tobgr16; break;
453 case 0x46: conv = rgb24tobgr16; break;
454 case 0x48: conv = rgb32tobgr16; break;
455 case 0x63: conv = rgb15tobgr24; break;
456 case 0x64: conv = rgb16tobgr24; break;
457 case 0x66: conv = rgb24tobgr24; break;
458 case 0x68: conv = rgb32tobgr24; break;
459 case 0x83: conv = rgb15tobgr32; break;
460 case 0x84: conv = rgb16tobgr32; break;
461 case 0x86: conv = rgb24tobgr32; break;
466 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
467 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
469 const uint8_t *srcPtr = src[0];
470 uint8_t *dstPtr = dst[0];
471 if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) &&
472 !isRGBA32(dstFormat))
473 srcPtr += ALT32_CORR;
475 if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) &&
476 !isRGBA32(srcFormat))
477 dstPtr += ALT32_CORR;
479 if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
480 !(srcStride[0] % srcBpp))
481 conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
482 srcSliceH * srcStride[0]);
485 dstPtr += dstStride[0] * srcSliceY;
487 for (i = 0; i < srcSliceH; i++) {
488 conv(srcPtr, dstPtr, c->srcW * srcBpp);
489 srcPtr += srcStride[0];
490 dstPtr += dstStride[0];
497 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
498 int srcStride[], int srcSliceY, int srcSliceH,
499 uint8_t *dst[], int dstStride[])
503 dst[0] + srcSliceY * dstStride[0],
504 dst[1] + (srcSliceY >> 1) * dstStride[1],
505 dst[2] + (srcSliceY >> 1) * dstStride[2],
507 dstStride[0], dstStride[1], srcStride[0]);
509 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
513 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
514 int srcStride[], int srcSliceY, int srcSliceH,
515 uint8_t *dst[], int dstStride[])
517 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
518 dst[0], dstStride[0]);
520 planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
521 srcSliceH >> 2, srcStride[1], dstStride[1]);
522 planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
523 srcSliceH >> 2, srcStride[2], dstStride[2]);
525 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
529 /* unscaled copy like stuff (assumes nearly identical formats) */
530 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
531 int srcStride[], int srcSliceY, int srcSliceH,
532 uint8_t *dst[], int dstStride[])
534 if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
535 memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
538 const uint8_t *srcPtr = src[0];
539 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
542 /* universal length finder */
543 while (length + c->srcW <= FFABS(dstStride[0]) &&
544 length + c->srcW <= FFABS(srcStride[0]))
548 for (i = 0; i < srcSliceH; i++) {
549 memcpy(dstPtr, srcPtr, length);
550 srcPtr += srcStride[0];
551 dstPtr += dstStride[0];
557 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
558 uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
559 int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
560 for (i = 0; i < height; i++) {\
561 const uint8_t *dither= dithers[src_depth-9][i&7];\
562 for (j = 0; j < length-7; j+=8){\
563 dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
564 dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
565 dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
566 dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
567 dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
568 dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
569 dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
570 dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
572 for (; j < length; j++)\
573 dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
578 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
579 int srcStride[], int srcSliceY, int srcSliceH,
580 uint8_t *dst[], int dstStride[])
583 for (plane = 0; plane < 4; plane++) {
584 int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
585 int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
586 int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
587 const uint8_t *srcPtr = src[plane];
588 uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
589 int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
593 // ignore palette for GRAY8
594 if (plane == 1 && !dst[2]) continue;
595 if (!src[plane] || (plane == 1 && !src[2])) {
596 if (is16BPS(c->dstFormat))
598 fillPlane(dst[plane], dstStride[plane], length, height, y,
599 (plane == 3) ? 255 : 128);
601 if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
602 || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
604 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1 + 1;
605 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1 + 1;
606 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
607 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
609 if (dst_depth == 8) {
610 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
611 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
613 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
615 } else if (src_depth == 8) {
616 for (i = 0; i < height; i++) {
619 for (j = 0; j < length; j++)\
620 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
622 for (j = 0; j < length; j++)\
623 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
624 (srcPtr[j]>>(2*8-dst_depth)));\
626 if(isBE(c->dstFormat)){
631 dstPtr2 += dstStride[plane]/2;
632 srcPtr += srcStride[plane];
634 } else if (src_depth <= dst_depth) {
635 for (i = 0; i < height; i++) {
636 #define COPY_UP(r,w) \
638 for (j = 0; j < length; j++){ \
639 unsigned int v= r(&srcPtr2[j]);\
640 w(&dstPtr2[j], v<<(dst_depth-src_depth));\
643 for (j = 0; j < length; j++){ \
644 unsigned int v= r(&srcPtr2[j]);\
645 w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
646 (v>>(2*src_depth-dst_depth)));\
649 if(isBE(c->srcFormat)){
650 if(isBE(c->dstFormat)){
651 COPY_UP(AV_RB16, AV_WB16)
653 COPY_UP(AV_RB16, AV_WL16)
656 if(isBE(c->dstFormat)){
657 COPY_UP(AV_RL16, AV_WB16)
659 COPY_UP(AV_RL16, AV_WL16)
662 dstPtr2 += dstStride[plane]/2;
663 srcPtr2 += srcStride[plane]/2;
666 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
667 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
668 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
670 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
673 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
674 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
676 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
680 } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
681 isBE(c->srcFormat) != isBE(c->dstFormat)) {
683 for (i = 0; i < height; i++) {
684 for (j = 0; j < length; j++)
685 ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
686 srcPtr += srcStride[plane];
687 dstPtr += dstStride[plane];
689 } else if (dstStride[plane] == srcStride[plane] &&
690 srcStride[plane] > 0 && srcStride[plane] == length) {
691 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
692 height * dstStride[plane]);
694 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
696 for (i = 0; i < height; i++) {
697 memcpy(dstPtr, srcPtr, length);
698 srcPtr += srcStride[plane];
699 dstPtr += dstStride[plane];
708 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
709 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
710 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
713 void ff_get_unscaled_swscale(SwsContext *c)
715 const enum PixelFormat srcFormat = c->srcFormat;
716 const enum PixelFormat dstFormat = c->dstFormat;
717 const int flags = c->flags;
718 const int dstH = c->dstH;
721 needsDither = isAnyRGB(dstFormat) &&
722 c->dstFormatBpp < 24 &&
723 (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
726 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) &&
727 (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
728 c->swScale = planarToNv12Wrapper;
731 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUV422P ||
732 srcFormat == PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
733 !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
734 c->swScale = ff_yuv2rgb_get_func_ptr(c);
737 if (srcFormat == PIX_FMT_YUV410P &&
738 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
739 !(flags & SWS_BITEXACT)) {
740 c->swScale = yvu9ToYv12Wrapper;
744 if (srcFormat == PIX_FMT_BGR24 &&
745 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
746 !(flags & SWS_ACCURATE_RND))
747 c->swScale = bgr24ToYv12Wrapper;
749 /* RGB/BGR -> RGB/BGR (no dither needed forms) */
750 if ( isAnyRGB(srcFormat)
751 && isAnyRGB(dstFormat)
752 && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8
753 && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8
754 && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4
755 && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4
756 && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
757 && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
758 && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
759 && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
760 && srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE
761 && srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE
762 && srcFormat != PIX_FMT_BGR48LE && dstFormat != PIX_FMT_BGR48LE
763 && srcFormat != PIX_FMT_BGR48BE && dstFormat != PIX_FMT_BGR48BE
764 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
765 c->swScale= rgbToRgbWrapper;
767 #define isByteRGB(f) (\
768 f == PIX_FMT_RGB32 ||\
769 f == PIX_FMT_RGB32_1 ||\
770 f == PIX_FMT_RGB24 ||\
771 f == PIX_FMT_BGR32 ||\
772 f == PIX_FMT_BGR32_1 ||\
775 if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
776 c->swScale= planarRgbToRgbWrapper;
778 /* bswap 16 bits per pixel/component packed formats */
779 if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) ||
780 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48) ||
781 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) ||
782 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) ||
783 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) ||
784 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) ||
785 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48) ||
786 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) ||
787 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565))
788 c->swScale = packed_16bpc_bswap;
790 if (usePal(srcFormat) && isByteRGB(dstFormat))
791 c->swScale = palToRgbWrapper;
793 if (srcFormat == PIX_FMT_YUV422P) {
794 if (dstFormat == PIX_FMT_YUYV422)
795 c->swScale = yuv422pToYuy2Wrapper;
796 else if (dstFormat == PIX_FMT_UYVY422)
797 c->swScale = yuv422pToUyvyWrapper;
800 /* LQ converters if -sws 0 or -sws 4*/
801 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
803 if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
804 if (dstFormat == PIX_FMT_YUYV422)
805 c->swScale = planarToYuy2Wrapper;
806 else if (dstFormat == PIX_FMT_UYVY422)
807 c->swScale = planarToUyvyWrapper;
810 if (srcFormat == PIX_FMT_YUYV422 &&
811 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
812 c->swScale = yuyvToYuv420Wrapper;
813 if (srcFormat == PIX_FMT_UYVY422 &&
814 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
815 c->swScale = uyvyToYuv420Wrapper;
816 if (srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
817 c->swScale = yuyvToYuv422Wrapper;
818 if (srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
819 c->swScale = uyvyToYuv422Wrapper;
822 if ( srcFormat == dstFormat ||
823 (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) ||
824 (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) ||
825 (isPlanarYUV(srcFormat) && isGray(dstFormat)) ||
826 (isPlanarYUV(dstFormat) && isGray(srcFormat)) ||
827 (isGray(dstFormat) && isGray(srcFormat)) ||
828 (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
829 c->chrDstHSubSample == c->chrSrcHSubSample &&
830 c->chrDstVSubSample == c->chrSrcVSubSample &&
831 dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 &&
832 srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
834 if (isPacked(c->srcFormat))
835 c->swScale = packedCopyWrapper;
836 else /* Planar YUV or gray */
837 c->swScale = planarCopyWrapper;
841 ff_bfin_get_unscaled_swscale(c);
843 ff_swscale_get_unscaled_altivec(c);
846 static void reset_ptr(const uint8_t *src[], int format)
848 if (!isALPHA(format))
850 if (!isPlanar(format)) {
851 src[3] = src[2] = NULL;
858 static int check_image_pointers(const uint8_t * const data[4], enum PixelFormat pix_fmt,
859 const int linesizes[4])
861 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
864 for (i = 0; i < 4; i++) {
865 int plane = desc->comp[i].plane;
866 if (!data[plane] || !linesizes[plane])
874 * swscale wrapper, so we don't need to export the SwsContext.
875 * Assumes planar YUV to be in YUV order instead of YVU.
877 int attribute_align_arg sws_scale(struct SwsContext *c,
878 const uint8_t * const srcSlice[],
879 const int srcStride[], int srcSliceY,
880 int srcSliceH, uint8_t *const dst[],
881 const int dstStride[])
884 const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
885 uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] };
887 // do not mess up sliceDir if we have a "trailing" 0-size slice
891 if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
892 av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
895 if (!check_image_pointers((const uint8_t* const*)dst, c->dstFormat, dstStride)) {
896 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
900 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
901 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
904 if (c->sliceDir == 0) {
905 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
908 if (usePal(c->srcFormat)) {
909 for (i = 0; i < 256; i++) {
910 int p, r, g, b, y, u, v, a = 0xff;
911 if (c->srcFormat == PIX_FMT_PAL8) {
912 p = ((const uint32_t *)(srcSlice[1]))[i];
913 a = (p >> 24) & 0xFF;
914 r = (p >> 16) & 0xFF;
917 } else if (c->srcFormat == PIX_FMT_RGB8) {
919 g = ((i >> 2) & 7) * 36;
921 } else if (c->srcFormat == PIX_FMT_BGR8) {
923 g = ((i >> 3) & 7) * 36;
925 } else if (c->srcFormat == PIX_FMT_RGB4_BYTE) {
926 r = ( i >> 3 ) * 255;
927 g = ((i >> 1) & 3) * 85;
929 } else if (c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
932 assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
933 b = ( i >> 3 ) * 255;
934 g = ((i >> 1) & 3) * 85;
937 y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
938 u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
939 v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
940 c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
942 switch (c->dstFormat) {
947 c->pal_rgb[i]= r + (g<<8) + (b<<16) + (a<<24);
949 case PIX_FMT_BGR32_1:
953 c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
955 case PIX_FMT_RGB32_1:
959 c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
966 c->pal_rgb[i]= b + (g<<8) + (r<<16) + (a<<24);
971 // copy strides, so they can safely be modified
972 if (c->sliceDir == 1) {
973 // slices go from top to bottom
974 int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2],
976 int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2],
979 reset_ptr(src2, c->srcFormat);
980 reset_ptr((void*)dst2, c->dstFormat);
982 /* reset slice direction at end of frame */
983 if (srcSliceY + srcSliceH == c->srcH)
986 return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2,
989 // slices go from bottom to top => we flip the image internally
990 int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2],
992 int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2],
995 src2[0] += (srcSliceH - 1) * srcStride[0];
996 if (!usePal(c->srcFormat))
997 src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
998 src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
999 src2[3] += (srcSliceH - 1) * srcStride[3];
1000 dst2[0] += ( c->dstH - 1) * dstStride[0];
1001 dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1002 dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1003 dst2[3] += ( c->dstH - 1) * dstStride[3];
1005 reset_ptr(src2, c->srcFormat);
1006 reset_ptr((void*)dst2, c->dstFormat);
1008 /* reset slice direction at end of frame */
1012 return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH,
1013 srcSliceH, dst2, dstStride2);
1017 /* Convert the palette to the same packed 32-bit format as the palette */
1018 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
1019 int num_pixels, const uint8_t *palette)
1023 for (i = 0; i < num_pixels; i++)
1024 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
1027 /* Palette format: ABCD -> dst format: ABC */
1028 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
1029 int num_pixels, const uint8_t *palette)
1033 for (i = 0; i < num_pixels; i++) {
1035 dst[0] = palette[src[i] * 4 + 0];
1036 dst[1] = palette[src[i] * 4 + 1];
1037 dst[2] = palette[src[i] * 4 + 2];