diff options
Diffstat (limited to 'libswscale/output.c')
-rw-r--r-- | libswscale/output.c | 207 |
1 files changed, 105 insertions, 102 deletions
diff --git a/libswscale/output.c b/libswscale/output.c index 4953290018..8306298d64 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -1,20 +1,20 @@ /* - * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2001-2012 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 */ @@ -26,6 +26,7 @@ #include "libavutil/attributes.h" #include "libavutil/avutil.h" +#include "libavutil/avassert.h" #include "libavutil/bswap.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" @@ -36,24 +37,27 @@ #include "swscale.h" #include "swscale_internal.h" -DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_4)[2][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_2x2_4)[][8]={ { 1, 3, 1, 3, 1, 3, 1, 3, }, { 2, 0, 2, 0, 2, 0, 2, 0, }, +{ 1, 3, 1, 3, 1, 3, 1, 3, }, }; -DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_8)[2][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_2x2_8)[][8]={ { 6, 2, 6, 2, 6, 2, 6, 2, }, { 0, 4, 0, 4, 0, 4, 0, 4, }, +{ 6, 2, 6, 2, 6, 2, 6, 2, }, }; -DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[4][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[][8]={ { 8, 4, 11, 7, 8, 4, 11, 7, }, { 2, 14, 1, 13, 2, 14, 1, 13, }, { 10, 6, 9, 5, 10, 6, 9, 5, }, { 0, 12, 3, 15, 0, 12, 3, 15, }, +{ 8, 4, 11, 7, 8, 4, 11, 7, }, }; -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[][8]={ { 17, 9, 23, 15, 16, 8, 22, 14, }, { 5, 29, 3, 27, 4, 28, 2, 26, }, { 21, 13, 19, 11, 20, 12, 18, 10, }, @@ -62,9 +66,10 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={ { 4, 28, 2, 26, 5, 29, 3, 27, }, { 20, 12, 18, 10, 21, 13, 19, 11, }, { 1, 25, 7, 31, 0, 24, 6, 30, }, +{ 17, 9, 23, 15, 16, 8, 22, 14, }, }; -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[][8]={ { 0, 55, 14, 68, 3, 58, 17, 72, }, { 37, 18, 50, 32, 40, 22, 54, 35, }, { 9, 64, 5, 59, 13, 67, 8, 63, }, @@ -73,10 +78,11 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[8][8]={ { 39, 21, 52, 34, 38, 19, 51, 33, }, { 11, 66, 7, 62, 10, 65, 6, 60, }, { 48, 30, 43, 25, 47, 29, 42, 24, }, +{ 0, 55, 14, 68, 3, 58, 17, 72, }, }; #if 1 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[][8]={ {117, 62, 158, 103, 113, 58, 155, 100, }, { 34, 199, 21, 186, 31, 196, 17, 182, }, {144, 89, 131, 76, 141, 86, 127, 72, }, @@ -85,10 +91,11 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ { 28, 193, 14, 179, 38, 203, 24, 189, }, {138, 83, 124, 69, 148, 93, 134, 79, }, { 7, 172, 48, 213, 3, 168, 45, 210, }, +{117, 62, 158, 103, 113, 58, 155, 100, }, }; #elif 1 // tries to correct a gamma of 1.5 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[][8]={ { 0, 143, 18, 200, 2, 156, 25, 215, }, { 78, 28, 125, 64, 89, 36, 138, 74, }, { 10, 180, 3, 161, 16, 195, 8, 175, }, @@ -97,10 +104,11 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ { 85, 33, 134, 71, 81, 30, 130, 67, }, { 14, 190, 6, 171, 12, 185, 5, 166, }, {117, 57, 101, 44, 113, 54, 97, 41, }, +{ 0, 143, 18, 200, 2, 156, 25, 215, }, }; #elif 1 // tries to correct a gamma of 2.0 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[][8]={ { 0, 124, 8, 193, 0, 140, 12, 213, }, { 55, 14, 104, 42, 66, 19, 119, 52, }, { 3, 168, 1, 145, 6, 187, 3, 162, }, @@ -109,10 +117,11 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ { 62, 17, 114, 48, 58, 16, 109, 45, }, { 5, 181, 2, 157, 4, 175, 1, 151, }, { 95, 36, 78, 26, 90, 34, 74, 24, }, +{ 0, 124, 8, 193, 0, 140, 12, 213, }, }; #else // tries to correct a gamma of 2.5 -DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[][8]={ { 0, 107, 3, 187, 0, 125, 6, 212, }, { 39, 7, 86, 28, 49, 11, 102, 36, }, { 1, 158, 0, 131, 3, 180, 1, 151, }, @@ -121,6 +130,7 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ { 45, 9, 96, 33, 42, 8, 91, 30, }, { 2, 172, 1, 144, 2, 165, 0, 137, }, { 77, 23, 60, 15, 72, 21, 56, 14, }, +{ 0, 107, 3, 187, 0, 125, 6, 212, }, }; #endif @@ -136,7 +146,8 @@ yuv2plane1_16_c_template(const int32_t *src, uint16_t *dest, int dstW, int big_endian, int output_bits) { int i; - int shift = 19 - output_bits; + int shift = 3; + av_assert0(output_bits == 16); for (i = 0; i < dstW; i++) { int val = src[i] + (1 << (shift - 1)); @@ -150,10 +161,11 @@ yuv2planeX_16_c_template(const int16_t *filter, int filterSize, int big_endian, int output_bits) { int i; - int shift = 15 + 16 - output_bits; + int shift = 15; + av_assert0(output_bits == 16); for (i = 0; i < dstW; i++) { - int val = 1 << (30-output_bits); + int val = 1 << (shift - 1); int j; /* range of val is [0,0x7FFFFFFF], so 31 bits, but with lanczos/spline @@ -163,7 +175,7 @@ yuv2planeX_16_c_template(const int16_t *filter, int filterSize, * reasonable filterSize), and re-add that at the end. */ val -= 0x40000000; for (j = 0; j < filterSize; j++) - val += src[j][i] * filter[j]; + val += src[j][i] * (unsigned)filter[j]; output_pixel(&dest[i], val, 0x8000, int); } @@ -200,7 +212,7 @@ yuv2planeX_10_c_template(const int16_t *filter, int filterSize, int shift = 11 + 16 - output_bits; for (i = 0; i < dstW; i++) { - int val = 1 << (26-output_bits); + int val = 1 << (shift - 1); int j; for (j = 0; j < filterSize; j++) @@ -393,14 +405,14 @@ yuv2mono_1_c_template(SwsContext *c, const int16_t *buf0, for (i = 0; i < dstW; i += 8) { int acc = 0; - accumulate_bit(acc, (buf0[i + 0] >> 7) + d128[0]); - accumulate_bit(acc, (buf0[i + 1] >> 7) + d128[1]); - accumulate_bit(acc, (buf0[i + 2] >> 7) + d128[2]); - accumulate_bit(acc, (buf0[i + 3] >> 7) + d128[3]); - accumulate_bit(acc, (buf0[i + 4] >> 7) + d128[4]); - accumulate_bit(acc, (buf0[i + 5] >> 7) + d128[5]); - accumulate_bit(acc, (buf0[i + 6] >> 7) + d128[6]); - accumulate_bit(acc, (buf0[i + 7] >> 7) + d128[7]); + accumulate_bit(acc, ((buf0[i + 0] + 64) >> 7) + d128[0]); + accumulate_bit(acc, ((buf0[i + 1] + 64) >> 7) + d128[1]); + accumulate_bit(acc, ((buf0[i + 2] + 64) >> 7) + d128[2]); + accumulate_bit(acc, ((buf0[i + 3] + 64) >> 7) + d128[3]); + accumulate_bit(acc, ((buf0[i + 4] + 64) >> 7) + d128[4]); + accumulate_bit(acc, ((buf0[i + 5] + 64) >> 7) + d128[5]); + accumulate_bit(acc, ((buf0[i + 6] + 64) >> 7) + d128[6]); + accumulate_bit(acc, ((buf0[i + 7] + 64) >> 7) + d128[7]); output_pixel(*dest++, acc); } @@ -516,10 +528,12 @@ yuv2422_2_c_template(SwsContext *c, const int16_t *buf[2], int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19; int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha) >> 19; - Y1 = av_clip_uint8(Y1); - Y2 = av_clip_uint8(Y2); - U = av_clip_uint8(U); - V = av_clip_uint8(V); + if ((Y1 | Y2 | U | V) & 0x100) { + Y1 = av_clip_uint8(Y1); + Y2 = av_clip_uint8(Y2); + U = av_clip_uint8(U); + V = av_clip_uint8(V); + } output_pixels(i * 4, Y1, U, Y2, V); } @@ -536,10 +550,17 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { for (i = 0; i < ((dstW + 1) >> 1); i++) { - int Y1 = buf0[i * 2] >> 7; - int Y2 = buf0[i * 2 + 1] >> 7; - int U = ubuf0[i] >> 7; - int V = vbuf0[i] >> 7; + int Y1 = (buf0[i * 2 ]+64) >> 7; + int Y2 = (buf0[i * 2 + 1]+64) >> 7; + int U = (ubuf0[i] +64) >> 7; + int V = (vbuf0[i] +64) >> 7; + + if ((Y1 | Y2 | U | V) & 0x100) { + Y1 = av_clip_uint8(Y1); + Y2 = av_clip_uint8(Y2); + U = av_clip_uint8(U); + V = av_clip_uint8(V); + } Y1 = av_clip_uint8(Y1); Y2 = av_clip_uint8(Y2); @@ -551,10 +572,17 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0, } else { const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; for (i = 0; i < ((dstW + 1) >> 1); i++) { - int Y1 = buf0[i * 2] >> 7; - int Y2 = buf0[i * 2 + 1] >> 7; - int U = (ubuf0[i] + ubuf1[i]) >> 8; - int V = (vbuf0[i] + vbuf1[i]) >> 8; + int Y1 = (buf0[i * 2 ] + 64) >> 7; + int Y2 = (buf0[i * 2 + 1] + 64) >> 7; + int U = (ubuf0[i] + ubuf1[i]+128) >> 8; + int V = (vbuf0[i] + vbuf1[i]+128) >> 8; + + if ((Y1 | Y2 | U | V) & 0x100) { + Y1 = av_clip_uint8(Y1); + Y2 = av_clip_uint8(Y2); + U = av_clip_uint8(U); + V = av_clip_uint8(V); + } Y1 = av_clip_uint8(Y1); Y2 = av_clip_uint8(Y2); @@ -599,12 +627,12 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, int R, G, B; for (j = 0; j < lumFilterSize; j++) { - Y1 += lumSrc[j][i * 2] * lumFilter[j]; - Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j]; + Y1 += lumSrc[j][i * 2] * (unsigned)lumFilter[j]; + Y2 += lumSrc[j][i * 2 + 1] * (unsigned)lumFilter[j]; } - for (j = 0; j < chrFilterSize; j++) { - U += chrUSrc[j][i] * chrFilter[j]; - V += chrVSrc[j][i] * chrFilter[j]; + for (j = 0; j < chrFilterSize; j++) {; + U += chrUSrc[j][i] * (unsigned)chrFilter[j]; + V += chrVSrc[j][i] * (unsigned)chrFilter[j]; } // 8bit: 12+15=27; 16-bit: 12+19=31 @@ -812,7 +840,7 @@ YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48le, AV_PIX_FMT_BGR48LE) * correct RGB values into the destination buffer. */ static av_always_inline void -yuv2rgb_write(uint8_t *_dest, int i, unsigned Y1, unsigned Y2, +yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2, unsigned A1, unsigned A2, const void *_r, const void *_g, const void *_b, int y, enum AVPixelFormat target, int hasAlpha) @@ -848,6 +876,7 @@ yuv2rgb_write(uint8_t *_dest, int i, unsigned Y1, unsigned Y2, #define r_b ((target == AV_PIX_FMT_RGB24) ? r : b) #define b_r ((target == AV_PIX_FMT_RGB24) ? b : r) + dest[i * 6 + 0] = r_b[Y1]; dest[i * 6 + 1] = g[Y1]; dest[i * 6 + 2] = b_r[Y1]; @@ -953,12 +982,6 @@ yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter, Y2 >>= 19; U >>= 19; V >>= 19; - if ((Y1 | Y2 | U | V) & 0x100) { - Y1 = av_clip_uint8(Y1); - Y2 = av_clip_uint8(Y2); - U = av_clip_uint8(U); - V = av_clip_uint8(V); - } if (hasAlpha) { A1 = 1 << 18; A2 = 1 << 18; @@ -974,10 +997,9 @@ yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter, } } - /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/ - r = c->table_rV[V]; - g = (c->table_gU[U] + c->table_gV[V]); - b = c->table_bU[U]; + r = c->table_rV[V + YUVRGB_TABLE_HEADROOM]; + g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]); + b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; yuv2rgb_write(dest, i, Y1, Y2, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0, r, g, b, y, target, hasAlpha); @@ -1006,16 +1028,9 @@ yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2], int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19; int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha) >> 19; int A1, A2; - const void *r, *g, *b; - - Y1 = av_clip_uint8(Y1); - Y2 = av_clip_uint8(Y2); - U = av_clip_uint8(U); - V = av_clip_uint8(V); - - r = c->table_rV[V]; - g = (c->table_gU[U] + c->table_gV[V]); - b = c->table_bU[U]; + const void *r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + *g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + *b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; if (hasAlpha) { A1 = (abuf0[i * 2 ] * yalpha1 + abuf1[i * 2 ] * yalpha) >> 19; @@ -1041,25 +1056,18 @@ yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0, if (uvalpha < 2048) { for (i = 0; i < ((dstW + 1) >> 1); i++) { - int Y1 = buf0[i * 2] >> 7; - int Y2 = buf0[i * 2 + 1] >> 7; - int U = ubuf0[i] >> 7; - int V = vbuf0[i] >> 7; + int Y1 = (buf0[i * 2 ] + 64) >> 7; + int Y2 = (buf0[i * 2 + 1] + 64) >> 7; + int U = (ubuf0[i] + 64) >> 7; + int V = (vbuf0[i] + 64) >> 7; int A1, A2; - const void *r, *g, *b; - - Y1 = av_clip_uint8(Y1); - Y2 = av_clip_uint8(Y2); - U = av_clip_uint8(U); - V = av_clip_uint8(V); - - r = c->table_rV[V]; - g = (c->table_gU[U] + c->table_gV[V]); - b = c->table_bU[U]; + const void *r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + *g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + *b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; if (hasAlpha) { - A1 = abuf0[i * 2 ] >> 7; - A2 = abuf0[i * 2 + 1] >> 7; + A1 = abuf0[i * 2 ] * 255 + 16384 >> 15; + A2 = abuf0[i * 2 + 1] * 255 + 16384 >> 15; A1 = av_clip_uint8(A1); A2 = av_clip_uint8(A2); } @@ -1070,25 +1078,18 @@ yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0, } else { const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; for (i = 0; i < ((dstW + 1) >> 1); i++) { - int Y1 = buf0[i * 2] >> 7; - int Y2 = buf0[i * 2 + 1] >> 7; - int U = (ubuf0[i] + ubuf1[i]) >> 8; - int V = (vbuf0[i] + vbuf1[i]) >> 8; + int Y1 = (buf0[i * 2 ] + 64) >> 7; + int Y2 = (buf0[i * 2 + 1] + 64) >> 7; + int U = (ubuf0[i] + ubuf1[i] + 128) >> 8; + int V = (vbuf0[i] + vbuf1[i] + 128) >> 8; int A1, A2; - const void *r, *g, *b; - - Y1 = av_clip_uint8(Y1); - Y2 = av_clip_uint8(Y2); - U = av_clip_uint8(U); - V = av_clip_uint8(V); - - r = c->table_rV[V]; - g = (c->table_gU[U] + c->table_gV[V]); - b = c->table_bU[U]; + const void *r = c->table_rV[V + YUVRGB_TABLE_HEADROOM], + *g = (c->table_gU[U + YUVRGB_TABLE_HEADROOM] + c->table_gV[V + YUVRGB_TABLE_HEADROOM]), + *b = c->table_bU[U + YUVRGB_TABLE_HEADROOM]; if (hasAlpha) { - A1 = abuf0[i * 2 ] >> 7; - A2 = abuf0[i * 2 + 1] >> 7; + A1 = (abuf0[i * 2 ] + 64) >> 7; + A2 = (abuf0[i * 2 + 1] + 64) >> 7; A1 = av_clip_uint8(A1); A2 = av_clip_uint8(A2); } @@ -1164,9 +1165,9 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, for (i = 0; i < dstW; i++) { int j; - int Y = 0; - int U = -128 << 19; - int V = -128 << 19; + int Y = 1<<9; + int U = (1<<9)-(128 << 19); + int V = (1<<9)-(128 << 19); int R, G, B, A; for (j = 0; j < lumFilterSize; j++) { @@ -1180,7 +1181,7 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, U >>= 10; V >>= 10; if (hasAlpha) { - A = 1 << 21; + A = 1 << 18; for (j = 0; j < lumFilterSize; j++) { A += alpSrc[j][i] * lumFilter[j]; } @@ -1223,7 +1224,6 @@ yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter, dest[1] = B >> 22; dest[2] = G >> 22; dest[3] = R >> 22; - dest += 4; break; case AV_PIX_FMT_BGR24: dest[0] = B >> 22; @@ -1355,7 +1355,10 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, *yuv2packedX = yuv2bgr24_full_X_c; break; } + if(!*yuv2packedX) + goto YUV_PACKED; } else { + YUV_PACKED: switch (dstFormat) { case AV_PIX_FMT_RGB48LE: *yuv2packed1 = yuv2rgb48le_1_c; |