From 4e3e333a79272944b40695166438359b376d7864 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 5 Jul 2011 12:49:11 -0700 Subject: swscale: error dithering for 16/9/10-bit to 8-bit. Based on a somewhat similar idea in FFmpeg's swscale copy. --- libswscale/swscale.c | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'libswscale/swscale.c') diff --git a/libswscale/swscale.c b/libswscale/swscale.c index db4d231e13..dd9f4a108f 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -182,6 +182,18 @@ DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={ { 77, 23, 60, 15, 72, 21, 56, 14, }, }; #endif +DECLARE_ALIGNED(8, const uint8_t, dither_8x8_128)[8][8] = { +{ 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,}, +}; +DECLARE_ALIGNED(8, const uint8_t, ff_sws_pb_64)[8] = +{ 64, 64, 64, 64, 64, 64, 64, 64 }; static av_always_inline void yuv2yuvX16_c_template(const int16_t *lumFilter, const int32_t **lumSrc, @@ -285,10 +297,11 @@ static void yuv2yuvX_c(SwsContext *c, const int16_t *lumFilter, uint8_t *yDest = dest[0], *uDest = dest[1], *vDest = dest[2], *aDest = CONFIG_SWSCALE_ALPHA ? dest[3] : NULL; int i; + const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8; //FIXME Optimize (just quickly written not optimized..) for (i=0; ilumDither8, *chrDither = c->chrDither8; for (i=0; i>7; + int val = (lumSrc[i]+ lumDither[i & 7]) >> 7; yDest[i]= av_clip_uint8(val); } if (uDest) for (i=0; i>7; - int v=(chrVSrc[i]+64)>>7; + int u = (chrUSrc[i] + chrDither[i & 7]) >> 7; + int v = (chrVSrc[i] + chrDither[(i + 3) & 7]) >> 7; uDest[i]= av_clip_uint8(u); vDest[i]= av_clip_uint8(v); } if (CONFIG_SWSCALE_ALPHA && aDest) for (i=0; i>7; + int val = (alpSrc[i] + lumDither[i & 7]) >> 7; aDest[i]= av_clip_uint8(val); } } @@ -359,11 +373,12 @@ static void yuv2nv12X_c(SwsContext *c, const int16_t *lumFilter, { uint8_t *yDest = dest[0], *uDest = dest[1]; enum PixelFormat dstFormat = c->dstFormat; + const uint8_t *lumDither = c->lumDither8, *chrDither = c->chrDither8; //FIXME Optimize (just quickly written not optimized..) int i; for (i=0; iyuv2packed1; yuv2packed2_fn yuv2packed2 = c->yuv2packed2; yuv2packedX_fn yuv2packedX = c->yuv2packedX; + int should_dither = is9_OR_10BPS(c->srcFormat) || is16BPS(c->srcFormat); /* vars which will change and which we need to store back in the context */ int dstY= c->dstY; @@ -2401,6 +2417,9 @@ static int swScale(SwsContext *c, const uint8_t* src[], lastInChrBuf= -1; } + if (!should_dither) { + c->chrDither8 = c->lumDither8 = ff_sws_pb_64; + } lastDstY= dstY; for (;dstY < dstH; dstY++) { @@ -2490,6 +2509,10 @@ static int swScale(SwsContext *c, const uint8_t* src[], #if HAVE_MMX updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, lastInLumBuf, lastInChrBuf); #endif + if (should_dither) { + c->chrDither8 = dither_8x8_128[chrDstY & 7]; + c->lumDither8 = dither_8x8_128[dstY & 7]; + } if (dstY >= dstH-2) { // hmm looks like we can't use MMX here without overwriting this array's tail find_c_packed_planar_out_funcs(c, &yuv2yuv1, &yuv2yuvX, -- cgit v1.2.3