diff options
Diffstat (limited to 'libswscale/swscale_unscaled.c')
-rw-r--r-- | libswscale/swscale_unscaled.c | 946 |
1 files changed, 502 insertions, 444 deletions
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 3e5f49efeb..92b73575a0 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -1,20 +1,20 @@ /* - * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -23,7 +23,6 @@ #include <math.h> #include <stdio.h> #include "config.h" -#include <assert.h> #include "swscale.h" #include "swscale_internal.h" #include "rgb2rgb.h" @@ -33,58 +32,101 @@ #include "libavutil/mathematics.h" #include "libavutil/bswap.h" #include "libavutil/pixdesc.h" +#include "libavutil/avassert.h" -DECLARE_ALIGNED(8, static const uint8_t, dither_8x8_1)[8][8] = { - { 0, 1, 0, 1, 0, 1, 0, 1,}, - { 1, 0, 1, 0, 1, 0, 1, 0,}, - { 0, 1, 0, 1, 0, 1, 0, 1,}, - { 1, 0, 1, 0, 1, 0, 1, 0,}, - { 0, 1, 0, 1, 0, 1, 0, 1,}, - { 1, 0, 1, 0, 1, 0, 1, 0,}, - { 0, 1, 0, 1, 0, 1, 0, 1,}, - { 1, 0, 1, 0, 1, 0, 1, 0,}, -}; -DECLARE_ALIGNED(8, static const uint8_t, dither_8x8_3)[8][8] = { - { 1, 2, 1, 2, 1, 2, 1, 2,}, - { 3, 0, 3, 0, 3, 0, 3, 0,}, - { 1, 2, 1, 2, 1, 2, 1, 2,}, - { 3, 0, 3, 0, 3, 0, 3, 0,}, - { 1, 2, 1, 2, 1, 2, 1, 2,}, - { 3, 0, 3, 0, 3, 0, 3, 0,}, - { 1, 2, 1, 2, 1, 2, 1, 2,}, - { 3, 0, 3, 0, 3, 0, 3, 0,}, -}; -DECLARE_ALIGNED(8, static const uint8_t, dither_8x8_64)[8][8] = { - { 18, 34, 30, 46, 17, 33, 29, 45,}, - { 50, 2, 62, 14, 49, 1, 61, 13,}, - { 26, 42, 22, 38, 25, 41, 21, 37,}, - { 58, 10, 54, 6, 57, 9, 53, 5,}, - { 16, 32, 28, 44, 19, 35, 31, 47,}, - { 48, 0, 60, 12, 51, 3, 63, 15,}, - { 24, 40, 20, 36, 27, 43, 23, 39,}, - { 56, 8, 52, 4, 59, 11, 55, 7,}, -}; -DECLARE_ALIGNED(8, static const uint8_t, dither_8x8_256)[8][8] = { - { 72, 136, 120, 184, 68, 132, 116, 180,}, - { 200, 8, 248, 56, 196, 4, 244, 52,}, - { 104, 168, 88, 152, 100, 164, 84, 148,}, - { 232, 40, 216, 24, 228, 36, 212, 20,}, - { 64, 128, 102, 176, 76, 140, 124, 188,}, - { 192, 0, 240, 48, 204, 12, 252, 60,}, - { 96, 160, 80, 144, 108, 172, 92, 156,}, - { 224, 32, 208, 16, 236, 44, 220, 28,}, +DECLARE_ALIGNED(8, static const uint8_t, dithers)[8][8][8]={ +{ + { 0, 1, 0, 1, 0, 1, 0, 1,}, + { 1, 0, 1, 0, 1, 0, 1, 0,}, + { 0, 1, 0, 1, 0, 1, 0, 1,}, + { 1, 0, 1, 0, 1, 0, 1, 0,}, + { 0, 1, 0, 1, 0, 1, 0, 1,}, + { 1, 0, 1, 0, 1, 0, 1, 0,}, + { 0, 1, 0, 1, 0, 1, 0, 1,}, + { 1, 0, 1, 0, 1, 0, 1, 0,}, +},{ + { 1, 2, 1, 2, 1, 2, 1, 2,}, + { 3, 0, 3, 0, 3, 0, 3, 0,}, + { 1, 2, 1, 2, 1, 2, 1, 2,}, + { 3, 0, 3, 0, 3, 0, 3, 0,}, + { 1, 2, 1, 2, 1, 2, 1, 2,}, + { 3, 0, 3, 0, 3, 0, 3, 0,}, + { 1, 2, 1, 2, 1, 2, 1, 2,}, + { 3, 0, 3, 0, 3, 0, 3, 0,}, +},{ + { 2, 4, 3, 5, 2, 4, 3, 5,}, + { 6, 0, 7, 1, 6, 0, 7, 1,}, + { 3, 5, 2, 4, 3, 5, 2, 4,}, + { 7, 1, 6, 0, 7, 1, 6, 0,}, + { 2, 4, 3, 5, 2, 4, 3, 5,}, + { 6, 0, 7, 1, 6, 0, 7, 1,}, + { 3, 5, 2, 4, 3, 5, 2, 4,}, + { 7, 1, 6, 0, 7, 1, 6, 0,}, +},{ + { 4, 8, 7, 11, 4, 8, 7, 11,}, + { 12, 0, 15, 3, 12, 0, 15, 3,}, + { 6, 10, 5, 9, 6, 10, 5, 9,}, + { 14, 2, 13, 1, 14, 2, 13, 1,}, + { 4, 8, 7, 11, 4, 8, 7, 11,}, + { 12, 0, 15, 3, 12, 0, 15, 3,}, + { 6, 10, 5, 9, 6, 10, 5, 9,}, + { 14, 2, 13, 1, 14, 2, 13, 1,}, +},{ + { 9, 17, 15, 23, 8, 16, 14, 22,}, + { 25, 1, 31, 7, 24, 0, 30, 6,}, + { 13, 21, 11, 19, 12, 20, 10, 18,}, + { 29, 5, 27, 3, 28, 4, 26, 2,}, + { 8, 16, 14, 22, 9, 17, 15, 23,}, + { 24, 0, 30, 6, 25, 1, 31, 7,}, + { 12, 20, 10, 18, 13, 21, 11, 19,}, + { 28, 4, 26, 2, 29, 5, 27, 3,}, +},{ + { 18, 34, 30, 46, 17, 33, 29, 45,}, + { 50, 2, 62, 14, 49, 1, 61, 13,}, + { 26, 42, 22, 38, 25, 41, 21, 37,}, + { 58, 10, 54, 6, 57, 9, 53, 5,}, + { 16, 32, 28, 44, 19, 35, 31, 47,}, + { 48, 0, 60, 12, 51, 3, 63, 15,}, + { 24, 40, 20, 36, 27, 43, 23, 39,}, + { 56, 8, 52, 4, 59, 11, 55, 7,}, +},{ + { 18, 34, 30, 46, 17, 33, 29, 45,}, + { 50, 2, 62, 14, 49, 1, 61, 13,}, + { 26, 42, 22, 38, 25, 41, 21, 37,}, + { 58, 10, 54, 6, 57, 9, 53, 5,}, + { 16, 32, 28, 44, 19, 35, 31, 47,}, + { 48, 0, 60, 12, 51, 3, 63, 15,}, + { 24, 40, 20, 36, 27, 43, 23, 39,}, + { 56, 8, 52, 4, 59, 11, 55, 7,}, +},{ + { 36, 68, 60, 92, 34, 66, 58, 90,}, + { 100, 4,124, 28, 98, 2,122, 26,}, + { 52, 84, 44, 76, 50, 82, 42, 74,}, + { 116, 20,108, 12,114, 18,106, 10,}, + { 32, 64, 56, 88, 38, 70, 62, 94,}, + { 96, 0,120, 24,102, 6,126, 30,}, + { 48, 80, 40, 72, 54, 86, 46, 78,}, + { 112, 16,104, 8,118, 22,110, 14,}, +}}; + +static const uint16_t dither_scale[15][16]={ +{ 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,}, +{ 2, 3, 7, 7, 13, 13, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,}, +{ 3, 3, 4, 15, 15, 29, 57, 57, 57, 113, 113, 113, 113, 113, 113, 113,}, +{ 3, 4, 4, 5, 31, 31, 61, 121, 241, 241, 241, 241, 481, 481, 481, 481,}, +{ 3, 4, 5, 5, 6, 63, 63, 125, 249, 497, 993, 993, 993, 993, 993, 1985,}, +{ 3, 5, 6, 6, 6, 7, 127, 127, 253, 505, 1009, 2017, 4033, 4033, 4033, 4033,}, +{ 3, 5, 6, 7, 7, 7, 8, 255, 255, 509, 1017, 2033, 4065, 8129,16257,16257,}, +{ 3, 5, 6, 8, 8, 8, 8, 9, 511, 511, 1021, 2041, 4081, 8161,16321,32641,}, +{ 3, 5, 7, 8, 9, 9, 9, 9, 10, 1023, 1023, 2045, 4089, 8177,16353,32705,}, +{ 3, 5, 7, 8, 10, 10, 10, 10, 10, 11, 2047, 2047, 4093, 8185,16369,32737,}, +{ 3, 5, 7, 8, 10, 11, 11, 11, 11, 11, 12, 4095, 4095, 8189,16377,32753,}, +{ 3, 5, 7, 9, 10, 12, 12, 12, 12, 12, 12, 13, 8191, 8191,16381,32761,}, +{ 3, 5, 7, 9, 10, 12, 13, 13, 13, 13, 13, 13, 14,16383,16383,32765,}, +{ 3, 5, 7, 9, 10, 12, 14, 14, 14, 14, 14, 14, 14, 15,32767,32767,}, +{ 3, 5, 7, 9, 11, 12, 14, 15, 15, 15, 15, 15, 15, 15, 16,65535,}, }; -#define RGB2YUV_SHIFT 15 -#define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) -#define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5)) static void fillPlane(uint8_t *plane, int stride, int width, int height, int y, uint8_t val) @@ -97,27 +139,6 @@ static void fillPlane(uint8_t *plane, int stride, int width, int height, int y, } } -static void fill_plane9or10(uint8_t *plane, int stride, int width, - int height, int y, uint8_t val, - const int dst_depth, const int big_endian) -{ - int i, j; - uint16_t *dst = (uint16_t *) (plane + stride * y); -#define FILL8TO9_OR_10(wfunc) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < width; j++) { \ - wfunc(&dst[j], (val << (dst_depth - 8)) | \ - (val >> (16 - dst_depth))); \ - } \ - dst += stride / 2; \ - } - if (big_endian) { - FILL8TO9_OR_10(AV_WB16); - } else { - FILL8TO9_OR_10(AV_WL16); - } -} - static void copyPlane(const uint8_t *src, int srcStride, int srcSliceY, int srcSliceH, int width, uint8_t *dst, int dstStride) @@ -300,19 +321,23 @@ static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { - int i, j; - int srcstr = srcStride[0] >> 1; - int dststr = dstStride[0] >> 1; - uint16_t *dstPtr = (uint16_t *) dst[0]; - const uint16_t *srcPtr = (const uint16_t *) src[0]; - int min_stride = FFMIN(srcstr, dststr); - - for (i = 0; i < srcSliceH; i++) { - for (j = 0; j < min_stride; j++) { - dstPtr[j] = av_bswap16(srcPtr[j]); + int i, j, p; + + for (p = 0; p < 4; p++) { + int srcstr = srcStride[p] / 2; + int dststr = dstStride[p] / 2; + uint16_t *dstPtr = (uint16_t *) dst[p]; + const uint16_t *srcPtr = (const uint16_t *) src[p]; + int min_stride = FFMIN(FFABS(srcstr), FFABS(dststr)); + if(!dstPtr || !srcPtr) + continue; + for (i = 0; i < (srcSliceH >> c->chrDstVSubSample); i++) { + for (j = 0; j < min_stride; j++) { + dstPtr[j] = av_bswap16(srcPtr[j]); + } + srcPtr += srcstr; + dstPtr += dststr; } - srcPtr += srcstr; - dstPtr += dststr; } return srcSliceH; @@ -330,7 +355,7 @@ static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; const uint8_t *srcPtr = src[0]; - if (srcFormat == AV_PIX_FMT_Y400A) { + if (srcFormat == AV_PIX_FMT_GRAY8A) { switch (dstFormat) { case AV_PIX_FMT_RGB32 : conv = gray8aToPacked32; break; case AV_PIX_FMT_BGR32 : conv = gray8aToPacked32; break; @@ -352,7 +377,7 @@ static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], if (!conv) av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", - sws_format_name(srcFormat), sws_format_name(dstFormat)); + av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); else { for (i = 0; i < srcSliceH; i++) { conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb); @@ -364,6 +389,152 @@ static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], return srcSliceH; } +static void gbr16ptopacked16(const uint16_t *src[], int srcStride[], + uint8_t *dst, int dstStride, int srcSliceH, + int alpha, int swap, int bpp, int width) +{ + int x, h, i; + int scale_high = 16 - bpp, scale_low = (bpp - 8) * 2; + for (h = 0; h < srcSliceH; h++) { + uint16_t *dest = (uint16_t *)(dst + dstStride * h); + uint16_t component; + + switch(swap) { + case 3: + if (alpha) { + for (x = 0; x < width; x++) { + component = av_bswap16(src[0][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[1][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[2][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + component = av_bswap16(src[0][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[1][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + component = av_bswap16(src[2][x]); + *dest++ = av_bswap16(component << scale_high | component >> scale_low); + } + } + break; + case 2: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); + *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); + *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); + *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); + *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); + } + } + break; + case 1: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; + *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; + *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; + *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; + *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; + } + } + break; + default: + if (alpha) { + for (x = 0; x < width; x++) { + *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; + *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; + *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; + *dest++ = 0xffff; + } + } else { + for (x = 0; x < width; x++) { + *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; + *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; + *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; + } + } + } + for (i = 0; i < 3; i++) + src[i] += srcStride[i] >> 1; + } +} + +static int planarRgb16ToRgb16Wrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + const uint16_t *src102[] = { (uint16_t *)src[1], (uint16_t *)src[0], (uint16_t *)src[2] }; + const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1] }; + int stride102[] = { srcStride[1], srcStride[0], srcStride[2] }; + int stride201[] = { srcStride[2], srcStride[0], srcStride[1] }; + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); + int bits_per_sample = src_format->comp[0].depth_minus1 + 1; + int swap = 0; + if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) || + !HAVE_BIGENDIAN && src_format->flags & AV_PIX_FMT_FLAG_BE) + swap++; + if ( HAVE_BIGENDIAN && !(dst_format->flags & AV_PIX_FMT_FLAG_BE) || + !HAVE_BIGENDIAN && dst_format->flags & AV_PIX_FMT_FLAG_BE) + swap += 2; + + if ((src_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) != + (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) || + bits_per_sample <= 8) { + av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", + src_format->name, dst_format->name); + return srcSliceH; + } + switch (c->dstFormat) { + case AV_PIX_FMT_BGR48LE: + case AV_PIX_FMT_BGR48BE: + gbr16ptopacked16(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 0, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_RGB48LE: + case AV_PIX_FMT_RGB48BE: + gbr16ptopacked16(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 0, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_RGBA64LE: + case AV_PIX_FMT_RGBA64BE: + gbr16ptopacked16(src201, stride201, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 1, swap, bits_per_sample, c->srcW); + break; + case AV_PIX_FMT_BGRA64LE: + case AV_PIX_FMT_BGRA64BE: + gbr16ptopacked16(src102, stride102, + dst[0] + srcSliceY * dstStride[0], dstStride[0], + srcSliceH, 1, swap, bits_per_sample, c->srcW); + break; + default: + av_log(c, AV_LOG_ERROR, + "unsupported planar RGB conversion %s -> %s\n", + src_format->name, dst_format->name); + } + + return srcSliceH; +} + static void gbr24ptopacked24(const uint8_t *src[], int srcStride[], uint8_t *dst, int dstStride, int srcSliceH, int width) @@ -467,6 +638,22 @@ static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } +static int planarRgbToplanarRgbWrapper(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + dst[0], dstStride[0]); + copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW, + dst[1], dstStride[1]); + copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW, + dst[2], dstStride[2]); + if (dst[3]) + fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + + return srcSliceH; +} + static void packedtogbr24p(const uint8_t *src, int srcStride, uint8_t *dst[], int dstStride[], int srcSliceH, int alpha_first, int inc_size, int width) @@ -548,6 +735,20 @@ static int rgbToPlanarRgbWrapper(SwsContext *c, const uint8_t *src[], || (x) == AV_PIX_FMT_ABGR \ ) +#define isRGBA64(x) ( \ + (x) == AV_PIX_FMT_RGBA64LE \ + || (x) == AV_PIX_FMT_RGBA64BE \ + || (x) == AV_PIX_FMT_BGRA64LE \ + || (x) == AV_PIX_FMT_BGRA64BE \ + ) + +#define isRGB48(x) ( \ + (x) == AV_PIX_FMT_RGB48LE \ + || (x) == AV_PIX_FMT_RGB48BE \ + || (x) == AV_PIX_FMT_BGR48LE \ + || (x) == AV_PIX_FMT_BGR48BE \ + ) + /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int); static rgbConvFn findRgbConvFn(SwsContext *c) @@ -557,17 +758,11 @@ static rgbConvFn findRgbConvFn(SwsContext *c) const int srcId = c->srcFormatBpp; const int dstId = c->dstFormatBpp; rgbConvFn conv = NULL; - const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat); - const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat); #define IS_NOT_NE(bpp, desc) \ (((bpp + 7) >> 3) == 2 && \ (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN)) - /* if this is non-native rgb444/555/565, don't handle it here. */ - if (IS_NOT_NE(srcId, desc_src) || IS_NOT_NE(dstId, desc_dst)) - return NULL; - #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst) if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { @@ -583,6 +778,32 @@ static rgbConvFn findRgbConvFn(SwsContext *c) || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; else if (CONV_IS(BGRA, ABGR) || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; + } else if (isRGB48(srcFormat) && isRGB48(dstFormat)) { + if (CONV_IS(RGB48LE, BGR48LE) + || CONV_IS(BGR48LE, RGB48LE) + || CONV_IS(RGB48BE, BGR48BE) + || CONV_IS(BGR48BE, RGB48BE)) conv = rgb48tobgr48_nobswap; + else if (CONV_IS(RGB48LE, BGR48BE) + || CONV_IS(BGR48LE, RGB48BE) + || CONV_IS(RGB48BE, BGR48LE) + || CONV_IS(BGR48BE, RGB48LE)) conv = rgb48tobgr48_bswap; + } else if (isRGBA64(srcFormat) && isRGB48(dstFormat)) { + if (CONV_IS(RGBA64LE, BGR48LE) + || CONV_IS(BGRA64LE, RGB48LE) + || CONV_IS(RGBA64BE, BGR48BE) + || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap; + else if (CONV_IS(RGBA64LE, BGR48BE) + || CONV_IS(BGRA64LE, RGB48BE) + || CONV_IS(RGBA64BE, BGR48LE) + || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap; + else if (CONV_IS(RGBA64LE, RGB48LE) + || CONV_IS(BGRA64LE, BGR48LE) + || CONV_IS(RGBA64BE, RGB48BE) + || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap; + else if (CONV_IS(RGBA64LE, RGB48BE) + || CONV_IS(BGRA64LE, BGR48BE) + || CONV_IS(RGBA64BE, RGB48LE) + || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap; } else /* BGR -> BGR */ if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || @@ -624,6 +845,9 @@ static rgbConvFn findRgbConvFn(SwsContext *c) } } + if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) && !isRGBA32(srcFormat) && ALT32_CORR<0) + return NULL; + return conv; } @@ -635,16 +859,21 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], { const enum AVPixelFormat srcFormat = c->srcFormat; const enum AVPixelFormat dstFormat = c->dstFormat; + const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); const int srcBpp = (c->srcFormatBpp + 7) >> 3; const int dstBpp = (c->dstFormatBpp + 7) >> 3; rgbConvFn conv = findRgbConvFn(c); if (!conv) { av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", - sws_format_name(srcFormat), sws_format_name(dstFormat)); + av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); } else { const uint8_t *srcPtr = src[0]; uint8_t *dstPtr = dst[0]; + int src_bswap = IS_NOT_NE(c->srcFormatBpp, desc_src); + int dst_bswap = IS_NOT_NE(c->dstFormatBpp, desc_dst); + if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) && !isRGBA32(dstFormat)) srcPtr += ALT32_CORR; @@ -654,15 +883,23 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], dstPtr += ALT32_CORR; if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 && - !(srcStride[0] % srcBpp)) + !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap) conv(srcPtr, dstPtr + dstStride[0] * srcSliceY, srcSliceH * srcStride[0]); else { - int i; + int i, j; dstPtr += dstStride[0] * srcSliceY; for (i = 0; i < srcSliceH; i++) { - conv(srcPtr, dstPtr, c->srcW * srcBpp); + if(src_bswap) { + for(j=0; j<c->srcW; j++) + ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]); + conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp); + }else + conv(srcPtr, dstPtr, c->srcW * srcBpp); + if(dst_bswap) + for(j=0; j<c->srcW; j++) + ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]); srcPtr += srcStride[0]; dstPtr += dstStride[0]; } @@ -675,13 +912,14 @@ static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { - rgb24toyv12( + ff_rgb24toyv12( src[0], dst[0] + srcSliceY * dstStride[0], dst[1] + (srcSliceY >> 1) * dstStride[1], dst[2] + (srcSliceY >> 1) * dstStride[2], c->srcW, srcSliceH, - dstStride[0], dstStride[1], srcStride[0]); + dstStride[0], dstStride[1], srcStride[0], + c->input_rgb2yuv_table); if (dst[3]) fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); return srcSliceH; @@ -720,7 +958,7 @@ static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], while (length + c->srcW <= FFABS(dstStride[0]) && length + c->srcW <= FFABS(srcStride[0])) length += c->srcW; - assert(length != 0); + av_assert1(length != 0); for (i = 0; i < srcSliceH; i++) { memcpy(dstPtr, srcPtr, length); @@ -731,25 +969,25 @@ static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], return srcSliceH; } -#define clip9(x) av_clip_uintp2(x, 9) -#define clip10(x) av_clip_uintp2(x, 10) -#define DITHER_COPY(dst, dstStride, wfunc, src, srcStride, rfunc, dithers, shift, clip) \ - for (i = 0; i < height; i++) { \ - const uint8_t *dither = dithers[i & 7]; \ - for (j = 0; j < length - 7; j += 8) { \ - wfunc(&dst[j + 0], clip((rfunc(&src[j + 0]) + dither[0]) >> shift)); \ - wfunc(&dst[j + 1], clip((rfunc(&src[j + 1]) + dither[1]) >> shift)); \ - wfunc(&dst[j + 2], clip((rfunc(&src[j + 2]) + dither[2]) >> shift)); \ - wfunc(&dst[j + 3], clip((rfunc(&src[j + 3]) + dither[3]) >> shift)); \ - wfunc(&dst[j + 4], clip((rfunc(&src[j + 4]) + dither[4]) >> shift)); \ - wfunc(&dst[j + 5], clip((rfunc(&src[j + 5]) + dither[5]) >> shift)); \ - wfunc(&dst[j + 6], clip((rfunc(&src[j + 6]) + dither[6]) >> shift)); \ - wfunc(&dst[j + 7], clip((rfunc(&src[j + 7]) + dither[7]) >> shift)); \ - } \ - for (; j < length; j++) \ - wfunc(&dst[j], (rfunc(&src[j]) + dither[j & 7]) >> shift); \ - dst += dstStride; \ - src += srcStride; \ +#define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\ + uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\ + int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\ + for (i = 0; i < height; i++) {\ + const uint8_t *dither= dithers[src_depth-9][i&7];\ + for (j = 0; j < length-7; j+=8){\ + dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\ + dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\ + dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\ + dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\ + dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\ + dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\ + dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\ + dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\ + }\ + for (; j < length; j++)\ + dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\ + dst += dstStride;\ + src += srcStride;\ } static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], @@ -760,174 +998,132 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); int plane, i, j; for (plane = 0; plane < 4; plane++) { - int length = (plane == 0 || plane == 3) ? c->srcW : -((-c->srcW ) >> c->chrDstHSubSample); - int y = (plane == 0 || plane == 3) ? srcSliceY: -((-srcSliceY) >> c->chrDstVSubSample); - int height = (plane == 0 || plane == 3) ? srcSliceH: -((-srcSliceH) >> c->chrDstVSubSample); + int length = (plane == 0 || plane == 3) ? c->srcW : FF_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); + int y = (plane == 0 || plane == 3) ? srcSliceY: FF_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); + int height = (plane == 0 || plane == 3) ? srcSliceH: FF_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); const uint8_t *srcPtr = src[plane]; uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; + int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0); if (!dst[plane]) continue; // ignore palette for GRAY8 if (plane == 1 && !dst[2]) continue; if (!src[plane] || (plane == 1 && !src[2])) { - int val = (plane == 3) ? 255 : 128; - if (is16BPS(c->dstFormat)) - length *= 2; - if (is9_OR_10BPS(c->dstFormat)) { - fill_plane9or10(dst[plane], dstStride[plane], - length, height, y, val, - desc_dst->comp[plane].depth_minus1 + 1, - isBE(c->dstFormat)); - } else + if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) { + fillPlane16(dst[plane], dstStride[plane], length, height, y, + plane == 3, desc_dst->comp[plane].depth_minus1, + isBE(c->dstFormat)); + } else { fillPlane(dst[plane], dstStride[plane], length, height, y, - val); + (plane == 3) ? 255 : 128); + } } else { - if (is9_OR_10BPS(c->srcFormat)) { + if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat) + || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat)) + ) { const int src_depth = desc_src->comp[plane].depth_minus1 + 1; const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1; const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; + uint16_t *dstPtr2 = (uint16_t*)dstPtr; - if (is16BPS(c->dstFormat)) { - uint16_t *dstPtr2 = (uint16_t *) dstPtr; -#define COPY9_OR_10TO16(rfunc, wfunc) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < length; j++) { \ - int srcpx = rfunc(&srcPtr2[j]); \ - wfunc(&dstPtr2[j], (srcpx << (16 - src_depth)) | (srcpx >> (2 * src_depth - 16))); \ - } \ - dstPtr2 += dstStride[plane] / 2; \ - srcPtr2 += srcStride[plane] / 2; \ + if (dst_depth == 8) { + if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ + DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , ) + } else { + DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, ) } - if (isBE(c->dstFormat)) { - if (isBE(c->srcFormat)) { - COPY9_OR_10TO16(AV_RB16, AV_WB16); - } else { - COPY9_OR_10TO16(AV_RL16, AV_WB16); + } else if (src_depth == 8) { + for (i = 0; i < height; i++) { + #define COPY816(w)\ + if(shiftonly){\ + for (j = 0; j < length; j++)\ + w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\ + }else{\ + for (j = 0; j < length; j++)\ + w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\ + (srcPtr[j]>>(2*8-dst_depth)));\ } - } else { - if (isBE(c->srcFormat)) { - COPY9_OR_10TO16(AV_RB16, AV_WL16); + if(isBE(c->dstFormat)){ + COPY816(AV_WB16) } else { - COPY9_OR_10TO16(AV_RL16, AV_WL16); + COPY816(AV_WL16) } + dstPtr2 += dstStride[plane]/2; + srcPtr += srcStride[plane]; } - } else if (is9_OR_10BPS(c->dstFormat)) { - uint16_t *dstPtr2 = (uint16_t *) dstPtr; -#define COPY9_OR_10TO9_OR_10(loop) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < length; j++) { \ - loop; \ - } \ - dstPtr2 += dstStride[plane] / 2; \ - srcPtr2 += srcStride[plane] / 2; \ - } -#define COPY9_OR_10TO9_OR_10_2(rfunc, wfunc) \ - if (dst_depth > src_depth) { \ - COPY9_OR_10TO9_OR_10(int srcpx = rfunc(&srcPtr2[j]); \ - wfunc(&dstPtr2[j], (srcpx << 1) | (srcpx >> 9))); \ - } else if (dst_depth < src_depth) { \ - DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - dither_8x8_1, 1, clip9); \ - } else { \ - COPY9_OR_10TO9_OR_10(wfunc(&dstPtr2[j], rfunc(&srcPtr2[j]))); \ - } - if (isBE(c->dstFormat)) { - if (isBE(c->srcFormat)) { - COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WB16); - } else { - COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WB16); + } else if (src_depth <= dst_depth) { + int orig_length = length; + for (i = 0; i < height; i++) { + if(isBE(c->srcFormat) == HAVE_BIGENDIAN && + isBE(c->dstFormat) == HAVE_BIGENDIAN && + shiftonly) { + unsigned shift = dst_depth - src_depth; + length = orig_length; +#if HAVE_FAST_64BIT +#define FAST_COPY_UP(shift) \ + for (j = 0; j < length - 3; j += 4) { \ + uint64_t v = AV_RN64A(srcPtr2 + j); \ + AV_WN64A(dstPtr2 + j, v << shift); \ + } \ + length &= 3; +#else +#define FAST_COPY_UP(shift) \ + for (j = 0; j < length - 1; j += 2) { \ + uint32_t v = AV_RN32A(srcPtr2 + j); \ + AV_WN32A(dstPtr2 + j, v << shift); \ + } \ + length &= 1; +#endif + switch (shift) + { + case 6: FAST_COPY_UP(6); break; + case 7: FAST_COPY_UP(7); break; + } } - } else { - if (isBE(c->srcFormat)) { - COPY9_OR_10TO9_OR_10_2(AV_RB16, AV_WL16); +#define COPY_UP(r,w) \ + if(shiftonly){\ + for (j = 0; j < length; j++){ \ + unsigned int v= r(&srcPtr2[j]);\ + w(&dstPtr2[j], v<<(dst_depth-src_depth));\ + }\ + }else{\ + for (j = 0; j < length; j++){ \ + unsigned int v= r(&srcPtr2[j]);\ + w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \ + (v>>(2*src_depth-dst_depth)));\ + }\ + } + if(isBE(c->srcFormat)){ + if(isBE(c->dstFormat)){ + COPY_UP(AV_RB16, AV_WB16) + } else { + COPY_UP(AV_RB16, AV_WL16) + } } else { - COPY9_OR_10TO9_OR_10_2(AV_RL16, AV_WL16); + if(isBE(c->dstFormat)){ + COPY_UP(AV_RL16, AV_WB16) + } else { + COPY_UP(AV_RL16, AV_WL16) + } } + dstPtr2 += dstStride[plane]/2; + srcPtr2 += srcStride[plane]/2; } } else { -#define W8(a, b) { *(a) = (b); } -#define COPY9_OR_10TO8(rfunc) \ - if (src_depth == 9) { \ - DITHER_COPY(dstPtr, dstStride[plane], W8, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - dither_8x8_1, 1, av_clip_uint8); \ - } else { \ - DITHER_COPY(dstPtr, dstStride[plane], W8, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - dither_8x8_3, 2, av_clip_uint8); \ - } - if (isBE(c->srcFormat)) { - COPY9_OR_10TO8(AV_RB16); - } else { - COPY9_OR_10TO8(AV_RL16); - } - } - } else if (is9_OR_10BPS(c->dstFormat)) { - const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1; - uint16_t *dstPtr2 = (uint16_t *) dstPtr; - - if (is16BPS(c->srcFormat)) { - const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; -#define COPY16TO9_OR_10(rfunc, wfunc) \ - if (dst_depth == 9) { \ - DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - ff_dither_8x8_128, 7, clip9); \ - } else { \ - DITHER_COPY(dstPtr2, dstStride[plane] / 2, wfunc, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - dither_8x8_64, 6, clip10); \ - } - if (isBE(c->dstFormat)) { - if (isBE(c->srcFormat)) { - COPY16TO9_OR_10(AV_RB16, AV_WB16); + if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ + if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ + DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , ) } else { - COPY16TO9_OR_10(AV_RL16, AV_WB16); + DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16) } - } else { - if (isBE(c->srcFormat)) { - COPY16TO9_OR_10(AV_RB16, AV_WL16); + }else{ + if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ + DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, ) } else { - COPY16TO9_OR_10(AV_RL16, AV_WL16); + DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16) } } - } else /* 8bit */ { -#define COPY8TO9_OR_10(wfunc) \ - for (i = 0; i < height; i++) { \ - for (j = 0; j < length; j++) { \ - const int srcpx = srcPtr[j]; \ - wfunc(&dstPtr2[j], (srcpx << (dst_depth - 8)) | (srcpx >> (16 - dst_depth))); \ - } \ - dstPtr2 += dstStride[plane] / 2; \ - srcPtr += srcStride[plane]; \ - } - if (isBE(c->dstFormat)) { - COPY8TO9_OR_10(AV_WB16); - } else { - COPY8TO9_OR_10(AV_WL16); - } - } - } else if (is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { - const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; -#define COPY16TO8(rfunc) \ - DITHER_COPY(dstPtr, dstStride[plane], W8, \ - srcPtr2, srcStride[plane] / 2, rfunc, \ - dither_8x8_256, 8, av_clip_uint8); - if (isBE(c->srcFormat)) { - COPY16TO8(AV_RB16); - } else { - COPY16TO8(AV_RL16); - } - } else if (!is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) { - for (i = 0; i < height; i++) { - for (j = 0; j < length; j++) { - dstPtr[ j << 1 ] = srcPtr[j]; - dstPtr[(j << 1) + 1] = srcPtr[j]; - } - srcPtr += srcStride[plane]; - dstPtr += dstStride[plane]; } } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) && isBE(c->srcFormat) != isBE(c->dstFormat)) { @@ -984,7 +1180,7 @@ void ff_get_unscaled_swscale(SwsContext *c) /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && - !(flags & SWS_ACCURATE_RND) && !(dstH & 1)) { + !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) { c->swscale = ff_yuv2rgb_get_func_ptr(c); } @@ -1005,6 +1201,10 @@ void ff_get_unscaled_swscale(SwsContext *c) && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) c->swscale = rgbToRgbWrapper; + if ((srcFormat == AV_PIX_FMT_GBRP && dstFormat == AV_PIX_FMT_GBRAP) || + (srcFormat == AV_PIX_FMT_GBRAP && dstFormat == AV_PIX_FMT_GBRP)) + c->swscale = planarRgbToplanarRgbWrapper; + #define isByteRGB(f) ( \ f == AV_PIX_FMT_RGB32 || \ f == AV_PIX_FMT_RGB32_1 || \ @@ -1016,6 +1216,17 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat)) c->swscale = planarRgbToRgbWrapper; + if ((srcFormat == AV_PIX_FMT_GBRP9LE || srcFormat == AV_PIX_FMT_GBRP9BE || + srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE || + srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE || + srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE || + srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE) && + (dstFormat == AV_PIX_FMT_RGB48LE || dstFormat == AV_PIX_FMT_RGB48BE || + dstFormat == AV_PIX_FMT_BGR48LE || dstFormat == AV_PIX_FMT_BGR48BE || + dstFormat == AV_PIX_FMT_RGBA64LE || dstFormat == AV_PIX_FMT_RGBA64BE || + dstFormat == AV_PIX_FMT_BGRA64LE || dstFormat == AV_PIX_FMT_BGRA64BE)) + c->swscale = planarRgb16ToRgb16Wrapper; + if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 && isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP) c->swscale = rgbToPlanarRgbWrapper; @@ -1023,23 +1234,40 @@ void ff_get_unscaled_swscale(SwsContext *c) /* bswap 16 bits per pixel/component packed formats */ if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP9) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP10) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) || - IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12)) + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P9) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P10) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P14) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P9) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P10) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P14) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P9) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P10) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P12) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P14) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16)) c->swscale = packed_16bpc_bswap; - if ((usePal(srcFormat) && ( - dstFormat == AV_PIX_FMT_RGB32 || - dstFormat == AV_PIX_FMT_RGB32_1 || - dstFormat == AV_PIX_FMT_RGB24 || - dstFormat == AV_PIX_FMT_BGR32 || - dstFormat == AV_PIX_FMT_BGR32_1 || - dstFormat == AV_PIX_FMT_BGR24))) + if (usePal(srcFormat) && isByteRGB(dstFormat)) c->swscale = palToRgbWrapper; if (srcFormat == AV_PIX_FMT_YUV422P) { @@ -1070,13 +1298,14 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P) c->swscale = uyvyToYuv422Wrapper; +#define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_GRAY8A) /* simple copy */ if ( srcFormat == dstFormat || (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) || (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) || - (isPlanarYUV(srcFormat) && isGray(dstFormat)) || - (isPlanarYUV(dstFormat) && isGray(srcFormat)) || - (isGray(dstFormat) && isGray(srcFormat)) || + (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || + (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) || + (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && c->chrDstHSubSample == c->chrSrcHSubSample && c->chrDstVSubSample == c->chrSrcVSubSample && @@ -1095,177 +1324,6 @@ void ff_get_unscaled_swscale(SwsContext *c) ff_get_unscaled_swscale_ppc(c); } -static void reset_ptr(const uint8_t *src[], int format) -{ - if (!isALPHA(format)) - src[3] = NULL; - if (!isPlanar(format)) { - src[3] = src[2] = NULL; - - if (!usePal(format)) - src[1] = NULL; - } -} - -static int check_image_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, - const int linesizes[4]) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int i; - - for (i = 0; i < 4; i++) { - int plane = desc->comp[i].plane; - if (!data[plane] || !linesizes[plane]) - return 0; - } - - return 1; -} - -/** - * swscale wrapper, so we don't need to export the SwsContext. - * Assumes planar YUV to be in YUV order instead of YVU. - */ -int attribute_align_arg sws_scale(struct SwsContext *c, - const uint8_t * const srcSlice[], - const int srcStride[], int srcSliceY, - int srcSliceH, uint8_t *const dst[], - const int dstStride[]) -{ - int i; - const uint8_t *src2[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] }; - uint8_t *dst2[4] = { dst[0], dst[1], dst[2], dst[3] }; - - // do not mess up sliceDir if we have a "trailing" 0-size slice - if (srcSliceH == 0) - return 0; - - if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) { - av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); - return 0; - } - if (!check_image_pointers(dst, c->dstFormat, dstStride)) { - av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); - return 0; - } - - if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { - av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); - return 0; - } - if (c->sliceDir == 0) { - if (srcSliceY == 0) c->sliceDir = 1; else c->sliceDir = -1; - } - - if (usePal(c->srcFormat)) { - for (i = 0; i < 256; i++) { - int p, r, g, b, y, u, v; - if (c->srcFormat == AV_PIX_FMT_PAL8) { - p = ((const uint32_t *)(srcSlice[1]))[i]; - r = (p >> 16) & 0xFF; - g = (p >> 8) & 0xFF; - b = p & 0xFF; - } else if (c->srcFormat == AV_PIX_FMT_RGB8) { - r = ( i >> 5 ) * 36; - g = ((i >> 2) & 7) * 36; - b = ( i & 3) * 85; - } else if (c->srcFormat == AV_PIX_FMT_BGR8) { - b = ( i >> 6 ) * 85; - g = ((i >> 3) & 7) * 36; - r = ( i & 7) * 36; - } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) { - r = ( i >> 3 ) * 255; - g = ((i >> 1) & 3) * 85; - b = ( i & 1) * 255; - } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || - c->srcFormat == AV_PIX_FMT_Y400A) { - r = g = b = i; - } else { - assert(c->srcFormat == AV_PIX_FMT_BGR4_BYTE); - b = ( i >> 3 ) * 255; - g = ((i >> 1) & 3) * 85; - r = ( i & 1) * 255; - } - y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); - u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); - v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); - c->pal_yuv[i] = y + (u << 8) + (v << 16); - - switch (c->dstFormat) { - case AV_PIX_FMT_BGR32: -#if !HAVE_BIGENDIAN - case AV_PIX_FMT_RGB24: -#endif - c->pal_rgb[i] = r + (g << 8) + (b << 16); - break; - case AV_PIX_FMT_BGR32_1: -#if HAVE_BIGENDIAN - case AV_PIX_FMT_BGR24: -#endif - c->pal_rgb[i] = (r + (g << 8) + (b << 16)) << 8; - break; - case AV_PIX_FMT_RGB32_1: -#if HAVE_BIGENDIAN - case AV_PIX_FMT_RGB24: -#endif - c->pal_rgb[i] = (b + (g << 8) + (r << 16)) << 8; - break; - case AV_PIX_FMT_RGB32: -#if !HAVE_BIGENDIAN - case AV_PIX_FMT_BGR24: -#endif - default: - c->pal_rgb[i] = b + (g << 8) + (r << 16); - } - } - } - - // copy strides, so they can safely be modified - if (c->sliceDir == 1) { - // slices go from top to bottom - int srcStride2[4] = { srcStride[0], srcStride[1], srcStride[2], - srcStride[3] }; - int dstStride2[4] = { dstStride[0], dstStride[1], dstStride[2], - dstStride[3] }; - - reset_ptr(src2, c->srcFormat); - reset_ptr((const uint8_t **) dst2, c->dstFormat); - - /* reset slice direction at end of frame */ - if (srcSliceY + srcSliceH == c->srcH) - c->sliceDir = 0; - - return c->swscale(c, src2, srcStride2, srcSliceY, srcSliceH, dst2, - dstStride2); - } else { - // slices go from bottom to top => we flip the image internally - int srcStride2[4] = { -srcStride[0], -srcStride[1], -srcStride[2], - -srcStride[3] }; - int dstStride2[4] = { -dstStride[0], -dstStride[1], -dstStride[2], - -dstStride[3] }; - - src2[0] += (srcSliceH - 1) * srcStride[0]; - if (!usePal(c->srcFormat)) - src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1]; - src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2]; - src2[3] += (srcSliceH - 1) * srcStride[3]; - dst2[0] += ( c->dstH - 1) * dstStride[0]; - dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1]; - dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2]; - dst2[3] += ( c->dstH - 1) * dstStride[3]; - - reset_ptr(src2, c->srcFormat); - reset_ptr((const uint8_t **) dst2, c->dstFormat); - - /* reset slice direction at end of frame */ - if (!srcSliceY) - c->sliceDir = 0; - - return c->swscale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, - srcSliceH, dst2, dstStride2); - } -} - /* Convert the palette to the same packed 32-bit format as the palette */ void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) |