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];
247 for (i = 0; i < srcSliceH; i++) {
248 for (j = 0; j < srcstr; j++) {
249 dstPtr[j] = av_bswap16(srcPtr[j]);
258 static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
259 int srcSliceY, int srcSliceH, uint8_t *dst[],
262 const enum PixelFormat srcFormat = c->srcFormat;
263 const enum PixelFormat dstFormat = c->dstFormat;
264 void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels,
265 const uint8_t *palette) = NULL;
267 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
268 const uint8_t *srcPtr = src[0];
270 if (srcFormat == PIX_FMT_GRAY8A) {
272 case PIX_FMT_RGB32 : conv = gray8aToPacked32; break;
273 case PIX_FMT_BGR32 : conv = gray8aToPacked32; break;
274 case PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break;
275 case PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break;
276 case PIX_FMT_RGB24 : conv = gray8aToPacked24; break;
277 case PIX_FMT_BGR24 : conv = gray8aToPacked24; break;
279 } else if (usePal(srcFormat)) {
281 case PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break;
282 case PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break;
283 case PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break;
284 case PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break;
285 case PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break;
286 case PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break;
291 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
292 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
294 for (i = 0; i < srcSliceH; i++) {
295 conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb);
296 srcPtr += srcStride[0];
297 dstPtr += dstStride[0];
304 static void gbr24ptopacked24(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int width)
307 for (h = 0; h < srcSliceH; h++) {
308 uint8_t *dest = dst + dstStride * h;
309 for (x = 0; x < width; x++) {
315 for (i = 0; i < 3; i++)
316 src[i] += srcStride[i];
320 static void gbr24ptopacked32(const uint8_t* src[], int srcStride[], uint8_t* dst, int dstStride, int srcSliceH, int alpha_first, int width)
323 for (h = 0; h < srcSliceH; h++) {
324 uint8_t *dest = dst + dstStride * h;
327 for (x = 0; x < width; x++) {
334 for (x = 0; x < width; x++) {
342 for (i = 0; i < 3; i++)
343 src[i] += srcStride[i];
347 static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,
348 int srcSliceH, uint8_t* dst[], int dstStride[])
351 if (c->srcFormat != PIX_FMT_GBR24P) {
352 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
353 av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
357 switch (c->dstFormat) {
359 gbr24ptopacked24((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
360 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
364 gbr24ptopacked24((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
365 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, c->srcW);
371 gbr24ptopacked32((const uint8_t* []) {src[2], src[0], src[1]}, (int []) {srcStride[2], srcStride[0], srcStride[1]},
372 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
378 gbr24ptopacked32((const uint8_t* []) {src[1], src[0], src[2]}, (int []) {srcStride[1], srcStride[0], srcStride[2]},
379 dst[0] + srcSliceY * dstStride[0], dstStride[0], srcSliceH, alpha_first, c->srcW);
383 av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n",
384 av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat));
390 #define isRGBA32(x) ( \
391 (x) == PIX_FMT_ARGB \
392 || (x) == PIX_FMT_RGBA \
393 || (x) == PIX_FMT_BGRA \
394 || (x) == PIX_FMT_ABGR \
397 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
398 static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[],
399 int srcSliceY, int srcSliceH, uint8_t *dst[],
402 const enum PixelFormat srcFormat = c->srcFormat;
403 const enum PixelFormat dstFormat = c->dstFormat;
404 const int srcBpp = (c->srcFormatBpp + 7) >> 3;
405 const int dstBpp = (c->dstFormatBpp + 7) >> 3;
406 const int srcId = c->srcFormatBpp >> 2; /* 1:0, 4:1, 8:2, 15:3, 16:4, 24:6, 32:8 */
407 const int dstId = c->dstFormatBpp >> 2;
408 void (*conv)(const uint8_t *src, uint8_t *dst, int src_size) = NULL;
410 #define CONV_IS(src, dst) (srcFormat == PIX_FMT_##src && dstFormat == PIX_FMT_##dst)
412 if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) {
413 if ( CONV_IS(ABGR, RGBA)
414 || CONV_IS(ARGB, BGRA)
415 || CONV_IS(BGRA, ARGB)
416 || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210;
417 else if (CONV_IS(ABGR, ARGB)
418 || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321;
419 else if (CONV_IS(ABGR, BGRA)
420 || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230;
421 else if (CONV_IS(BGRA, RGBA)
422 || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103;
423 else if (CONV_IS(BGRA, ABGR)
424 || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012;
427 if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) ||
428 (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) {
429 switch (srcId | (dstId << 4)) {
430 case 0x34: conv = rgb16to15; break;
431 case 0x36: conv = rgb24to15; break;
432 case 0x38: conv = rgb32to15; break;
433 case 0x43: conv = rgb15to16; break;
434 case 0x46: conv = rgb24to16; break;
435 case 0x48: conv = rgb32to16; break;
436 case 0x63: conv = rgb15to24; break;
437 case 0x64: conv = rgb16to24; break;
438 case 0x68: conv = rgb32to24; break;
439 case 0x83: conv = rgb15to32; break;
440 case 0x84: conv = rgb16to32; break;
441 case 0x86: conv = rgb24to32; break;
443 } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) ||
444 (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) {
445 switch (srcId | (dstId << 4)) {
446 case 0x33: conv = rgb15tobgr15; break;
447 case 0x34: conv = rgb16tobgr15; break;
448 case 0x36: conv = rgb24tobgr15; break;
449 case 0x38: conv = rgb32tobgr15; break;
450 case 0x43: conv = rgb15tobgr16; break;
451 case 0x44: conv = rgb16tobgr16; break;
452 case 0x46: conv = rgb24tobgr16; break;
453 case 0x48: conv = rgb32tobgr16; break;
454 case 0x63: conv = rgb15tobgr24; break;
455 case 0x64: conv = rgb16tobgr24; break;
456 case 0x66: conv = rgb24tobgr24; break;
457 case 0x68: conv = rgb32tobgr24; break;
458 case 0x83: conv = rgb15tobgr32; break;
459 case 0x84: conv = rgb16tobgr32; break;
460 case 0x86: conv = rgb24tobgr32; break;
465 av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n",
466 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
468 const uint8_t *srcPtr = src[0];
469 uint8_t *dstPtr = dst[0];
470 if ((srcFormat == PIX_FMT_RGB32_1 || srcFormat == PIX_FMT_BGR32_1) &&
471 !isRGBA32(dstFormat))
472 srcPtr += ALT32_CORR;
474 if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) &&
475 !isRGBA32(srcFormat))
476 dstPtr += ALT32_CORR;
478 if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 &&
479 !(srcStride[0] % srcBpp))
480 conv(srcPtr, dstPtr + dstStride[0] * srcSliceY,
481 srcSliceH * srcStride[0]);
484 dstPtr += dstStride[0] * srcSliceY;
486 for (i = 0; i < srcSliceH; i++) {
487 conv(srcPtr, dstPtr, c->srcW * srcBpp);
488 srcPtr += srcStride[0];
489 dstPtr += dstStride[0];
496 static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
497 int srcStride[], int srcSliceY, int srcSliceH,
498 uint8_t *dst[], int dstStride[])
502 dst[0] + srcSliceY * dstStride[0],
503 dst[1] + (srcSliceY >> 1) * dstStride[1],
504 dst[2] + (srcSliceY >> 1) * dstStride[2],
506 dstStride[0], dstStride[1], srcStride[0]);
508 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
512 static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[],
513 int srcStride[], int srcSliceY, int srcSliceH,
514 uint8_t *dst[], int dstStride[])
516 copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW,
517 dst[0], dstStride[0]);
519 planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW,
520 srcSliceH >> 2, srcStride[1], dstStride[1]);
521 planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW,
522 srcSliceH >> 2, srcStride[2], dstStride[2]);
524 fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255);
528 /* unscaled copy like stuff (assumes nearly identical formats) */
529 static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
530 int srcStride[], int srcSliceY, int srcSliceH,
531 uint8_t *dst[], int dstStride[])
533 if (dstStride[0] == srcStride[0] && srcStride[0] > 0)
534 memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]);
537 const uint8_t *srcPtr = src[0];
538 uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY;
541 /* universal length finder */
542 while (length + c->srcW <= FFABS(dstStride[0]) &&
543 length + c->srcW <= FFABS(srcStride[0]))
547 for (i = 0; i < srcSliceH; i++) {
548 memcpy(dstPtr, srcPtr, length);
549 srcPtr += srcStride[0];
550 dstPtr += dstStride[0];
556 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
557 uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\
558 int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\
559 for (i = 0; i < height; i++) {\
560 const uint8_t *dither= dithers[src_depth-9][i&7];\
561 for (j = 0; j < length-7; j+=8){\
562 dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\
563 dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\
564 dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\
565 dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\
566 dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\
567 dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\
568 dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\
569 dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\
571 for (; j < length; j++)\
572 dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\
577 static int planarCopyWrapper(SwsContext *c, const uint8_t *src[],
578 int srcStride[], int srcSliceY, int srcSliceH,
579 uint8_t *dst[], int dstStride[])
582 for (plane = 0; plane < 4; plane++) {
583 int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample);
584 int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample);
585 int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample);
586 const uint8_t *srcPtr = src[plane];
587 uint8_t *dstPtr = dst[plane] + dstStride[plane] * y;
588 int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0);
592 // ignore palette for GRAY8
593 if (plane == 1 && !dst[2]) continue;
594 if (!src[plane] || (plane == 1 && !src[2])) {
595 if (is16BPS(c->dstFormat))
597 fillPlane(dst[plane], dstStride[plane], length, height, y,
598 (plane == 3) ? 255 : 128);
600 if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat)
601 || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat))
603 const int src_depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1 + 1;
604 const int dst_depth = av_pix_fmt_descriptors[c->dstFormat].comp[plane].depth_minus1 + 1;
605 const uint16_t *srcPtr2 = (const uint16_t *) srcPtr;
606 uint16_t *dstPtr2 = (uint16_t*)dstPtr;
608 if (dst_depth == 8) {
609 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
610 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , )
612 DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, )
614 } else if (src_depth == 8) {
615 for (i = 0; i < height; i++) {
618 for (j = 0; j < length; j++)\
619 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
621 for (j = 0; j < length; j++)\
622 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
623 (srcPtr[j]>>(2*8-dst_depth)));\
625 if(isBE(c->dstFormat)){
630 dstPtr2 += dstStride[plane]/2;
631 srcPtr += srcStride[plane];
633 } else if (src_depth <= dst_depth) {
634 for (i = 0; i < height; i++) {
635 #define COPY_UP(r,w) \
637 for (j = 0; j < length; j++){ \
638 unsigned int v= r(&srcPtr2[j]);\
639 w(&dstPtr2[j], v<<(dst_depth-src_depth));\
642 for (j = 0; j < length; j++){ \
643 unsigned int v= r(&srcPtr2[j]);\
644 w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
645 (v>>(2*src_depth-dst_depth)));\
648 if(isBE(c->srcFormat)){
649 if(isBE(c->dstFormat)){
650 COPY_UP(AV_RB16, AV_WB16)
652 COPY_UP(AV_RB16, AV_WL16)
655 if(isBE(c->dstFormat)){
656 COPY_UP(AV_RL16, AV_WB16)
658 COPY_UP(AV_RL16, AV_WL16)
661 dstPtr2 += dstStride[plane]/2;
662 srcPtr2 += srcStride[plane]/2;
665 if(isBE(c->srcFormat) == HAVE_BIGENDIAN){
666 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
667 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , )
669 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16)
672 if(isBE(c->dstFormat) == HAVE_BIGENDIAN){
673 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, )
675 DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16)
679 } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) &&
680 isBE(c->srcFormat) != isBE(c->dstFormat)) {
682 for (i = 0; i < height; i++) {
683 for (j = 0; j < length; j++)
684 ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]);
685 srcPtr += srcStride[plane];
686 dstPtr += dstStride[plane];
688 } else if (dstStride[plane] == srcStride[plane] &&
689 srcStride[plane] > 0 && srcStride[plane] == length) {
690 memcpy(dst[plane] + dstStride[plane] * y, src[plane],
691 height * dstStride[plane]);
693 if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat))
695 for (i = 0; i < height; i++) {
696 memcpy(dstPtr, srcPtr, length);
697 srcPtr += srcStride[plane];
698 dstPtr += dstStride[plane];
707 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
708 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
709 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
712 void ff_get_unscaled_swscale(SwsContext *c)
714 const enum PixelFormat srcFormat = c->srcFormat;
715 const enum PixelFormat dstFormat = c->dstFormat;
716 const int flags = c->flags;
717 const int dstH = c->dstH;
720 needsDither = isAnyRGB(dstFormat) &&
721 c->dstFormatBpp < 24 &&
722 (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat)));
725 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) &&
726 (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)) {
727 c->swScale = planarToNv12Wrapper;
730 if ((srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUV422P ||
731 srcFormat == PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) &&
732 !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) {
733 c->swScale = ff_yuv2rgb_get_func_ptr(c);
736 if (srcFormat == PIX_FMT_YUV410P &&
737 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
738 !(flags & SWS_BITEXACT)) {
739 c->swScale = yvu9ToYv12Wrapper;
743 if (srcFormat == PIX_FMT_BGR24 &&
744 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P) &&
745 !(flags & SWS_ACCURATE_RND))
746 c->swScale = bgr24ToYv12Wrapper;
748 /* RGB/BGR -> RGB/BGR (no dither needed forms) */
749 if ( isAnyRGB(srcFormat)
750 && isAnyRGB(dstFormat)
751 && srcFormat != PIX_FMT_BGR8 && dstFormat != PIX_FMT_BGR8
752 && srcFormat != PIX_FMT_RGB8 && dstFormat != PIX_FMT_RGB8
753 && srcFormat != PIX_FMT_BGR4 && dstFormat != PIX_FMT_BGR4
754 && srcFormat != PIX_FMT_RGB4 && dstFormat != PIX_FMT_RGB4
755 && srcFormat != PIX_FMT_BGR4_BYTE && dstFormat != PIX_FMT_BGR4_BYTE
756 && srcFormat != PIX_FMT_RGB4_BYTE && dstFormat != PIX_FMT_RGB4_BYTE
757 && srcFormat != PIX_FMT_MONOBLACK && dstFormat != PIX_FMT_MONOBLACK
758 && srcFormat != PIX_FMT_MONOWHITE && dstFormat != PIX_FMT_MONOWHITE
759 && srcFormat != PIX_FMT_RGB48LE && dstFormat != PIX_FMT_RGB48LE
760 && srcFormat != PIX_FMT_RGB48BE && dstFormat != PIX_FMT_RGB48BE
761 && srcFormat != PIX_FMT_BGR48LE && dstFormat != PIX_FMT_BGR48LE
762 && srcFormat != PIX_FMT_BGR48BE && dstFormat != PIX_FMT_BGR48BE
763 && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT))))
764 c->swScale= rgbToRgbWrapper;
766 #define isByteRGB(f) (\
767 f == PIX_FMT_RGB32 ||\
768 f == PIX_FMT_RGB32_1 ||\
769 f == PIX_FMT_RGB24 ||\
770 f == PIX_FMT_BGR32 ||\
771 f == PIX_FMT_BGR32_1 ||\
774 if (isAnyRGB(srcFormat) && isPlanar(srcFormat) && isByteRGB(dstFormat))
775 c->swScale= planarRgbToRgbWrapper;
777 /* bswap 16 bits per pixel/component packed formats */
778 if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) ||
779 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48) ||
780 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) ||
781 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) ||
782 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) ||
783 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) ||
784 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48) ||
785 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) ||
786 IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565))
787 c->swScale = packed_16bpc_bswap;
789 if (usePal(srcFormat) && isByteRGB(dstFormat))
790 c->swScale = palToRgbWrapper;
792 if (srcFormat == PIX_FMT_YUV422P) {
793 if (dstFormat == PIX_FMT_YUYV422)
794 c->swScale = yuv422pToYuy2Wrapper;
795 else if (dstFormat == PIX_FMT_UYVY422)
796 c->swScale = yuv422pToUyvyWrapper;
799 /* LQ converters if -sws 0 or -sws 4*/
800 if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) {
802 if (srcFormat == PIX_FMT_YUV420P || srcFormat == PIX_FMT_YUVA420P) {
803 if (dstFormat == PIX_FMT_YUYV422)
804 c->swScale = planarToYuy2Wrapper;
805 else if (dstFormat == PIX_FMT_UYVY422)
806 c->swScale = planarToUyvyWrapper;
809 if (srcFormat == PIX_FMT_YUYV422 &&
810 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
811 c->swScale = yuyvToYuv420Wrapper;
812 if (srcFormat == PIX_FMT_UYVY422 &&
813 (dstFormat == PIX_FMT_YUV420P || dstFormat == PIX_FMT_YUVA420P))
814 c->swScale = uyvyToYuv420Wrapper;
815 if (srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
816 c->swScale = yuyvToYuv422Wrapper;
817 if (srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
818 c->swScale = uyvyToYuv422Wrapper;
821 if ( srcFormat == dstFormat ||
822 (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P) ||
823 (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P) ||
824 (isPlanarYUV(srcFormat) && isGray(dstFormat)) ||
825 (isPlanarYUV(dstFormat) && isGray(srcFormat)) ||
826 (isGray(dstFormat) && isGray(srcFormat)) ||
827 (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) &&
828 c->chrDstHSubSample == c->chrSrcHSubSample &&
829 c->chrDstVSubSample == c->chrSrcVSubSample &&
830 dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 &&
831 srcFormat != PIX_FMT_NV12 && srcFormat != PIX_FMT_NV21))
833 if (isPacked(c->srcFormat))
834 c->swScale = packedCopyWrapper;
835 else /* Planar YUV or gray */
836 c->swScale = planarCopyWrapper;
840 ff_bfin_get_unscaled_swscale(c);
842 ff_swscale_get_unscaled_altivec(c);
845 static void reset_ptr(const uint8_t *src[], int format)
847 if (!isALPHA(format))
849 if (!isPlanar(format)) {
850 src[3] = src[2] = NULL;
857 static int check_image_pointers(const uint8_t * const data[4], enum PixelFormat pix_fmt,
858 const int linesizes[4])
860 const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt];
863 for (i = 0; i < 4; i++) {
864 int plane = desc->comp[i].plane;
865 if (!data[plane] || !linesizes[plane])
873 * swscale wrapper, so we don't need to export the SwsContext.
874 * Assumes planar YUV to be in YUV order instead of YVU.
876 int attribute_align_arg sws_scale(struct SwsContext *c,
877 const uint8_t * const srcSlice[],
878 const int srcStride[], int srcSliceY,
879 int srcSliceH, uint8_t *const dst[],
880 const int dstStride[])
883 const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
884 uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] };
886 // do not mess up sliceDir if we have a "trailing" 0-size slice
890 if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
891 av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
894 if (!check_image_pointers((const uint8_t* const*)dst, c->dstFormat, dstStride)) {
895 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
899 if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
900 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
903 if (c->sliceDir == 0) {
904 if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1;
907 if (usePal(c->srcFormat)) {
908 for (i = 0; i < 256; i++) {
909 int p, r, g, b, y, u, v, a = 0xff;
910 if (c->srcFormat == PIX_FMT_PAL8) {
911 p = ((const uint32_t *)(srcSlice[1]))[i];
912 a = (p >> 24) & 0xFF;
913 r = (p >> 16) & 0xFF;
916 } else if (c->srcFormat == PIX_FMT_RGB8) {
918 g = ((i >> 2) & 7) * 36;
920 } else if (c->srcFormat == PIX_FMT_BGR8) {
922 g = ((i >> 3) & 7) * 36;
924 } else if (c->srcFormat == PIX_FMT_RGB4_BYTE) {
925 r = ( i >> 3 ) * 255;
926 g = ((i >> 1) & 3) * 85;
928 } else if (c->srcFormat == PIX_FMT_GRAY8 || c->srcFormat == PIX_FMT_GRAY8A) {
931 assert(c->srcFormat == PIX_FMT_BGR4_BYTE);
932 b = ( i >> 3 ) * 255;
933 g = ((i >> 1) & 3) * 85;
936 y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
937 u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
938 v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
939 c->pal_yuv[i]= y + (u<<8) + (v<<16) + (a<<24);
941 switch (c->dstFormat) {
946 c->pal_rgb[i]= r + (g<<8) + (b<<16) + (a<<24);
948 case PIX_FMT_BGR32_1:
952 c->pal_rgb[i]= a + (r<<8) + (g<<16) + (b<<24);
954 case PIX_FMT_RGB32_1:
958 c->pal_rgb[i]= a + (b<<8) + (g<<16) + (r<<24);
965 c->pal_rgb[i]= b + (g<<8) + (r<<16) + (a<<24);
970 // copy strides, so they can safely be modified
971 if (c->sliceDir == 1) {
972 // slices go from top to bottom
973 int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2],
975 int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2],
978 reset_ptr(src2, c->srcFormat);
979 reset_ptr((void*)dst2, c->dstFormat);
981 /* reset slice direction at end of frame */
982 if (srcSliceY + srcSliceH == c->srcH)
985 return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2,
988 // slices go from bottom to top => we flip the image internally
989 int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2],
991 int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2],
994 src2[0] += (srcSliceH - 1) * srcStride[0];
995 if (!usePal(c->srcFormat))
996 src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
997 src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
998 src2[3] += (srcSliceH - 1) * srcStride[3];
999 dst2[0] += ( c->dstH - 1) * dstStride[0];
1000 dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1001 dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1002 dst2[3] += ( c->dstH - 1) * dstStride[3];
1004 reset_ptr(src2, c->srcFormat);
1005 reset_ptr((void*)dst2, c->dstFormat);
1007 /* reset slice direction at end of frame */
1011 return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH,
1012 srcSliceH, dst2, dstStride2);
1016 /* Convert the palette to the same packed 32-bit format as the palette */
1017 void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst,
1018 int num_pixels, const uint8_t *palette)
1022 for (i = 0; i < num_pixels; i++)
1023 ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]];
1026 /* Palette format: ABCD -> dst format: ABC */
1027 void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst,
1028 int num_pixels, const uint8_t *palette)
1032 for (i = 0; i < num_pixels; i++) {
1034 dst[0] = palette[src[i] * 4 + 0];
1035 dst[1] = palette[src[i] * 4 + 1];
1036 dst[2] = palette[src[i] * 4 + 2];