[FFmpeg-devel] libswscale/swscale_unscaled: fix DITHER_COPY macro

Submitted by Mateusz Brzostek on March 20, 2017, 9:48 a.m.

Details

Message ID 41eba3ee-b58d-dbf6-c7f9-5a37bb5564a6@msystem.waw.pl
State New
Headers show

Commit Message

Mateusz Brzostek March 20, 2017, 9:48 a.m.
W dniu 2017-03-20 o 10:00, Carl Eugen Hoyos pisze:
> 2017-03-15 22:52 GMT+01:00 Mateusz Brzostek <mateusz@msystem.waw.pl>:
>> Hello!
>>
>> There are 3 problems with DITHER_COPY macro in libswscale/swscale_unscaled.c:
>> 1) there is overflow in dithering from 12-bit to 10-bit (output value > 1023);
>> 2) for limit range the lower limit is not respected, for example from 10-bit to 8-bit value 64 is converted to 15;
>> 3) for many iteration of downscale/upscale of the same image the 200th iteration is significantly darker.
>>
>> The first bug is due to wrong dithers table (now it is OK only for 8-bit destination), fix is:
>> -        const uint8_t *dither= dithers[src_depth-9][i&7];\
>> +        const uint8_t *dither= dithers[src_depth-dst_depth-1][i&7];\
> I believe this implies that you could split your patch.
>
> Carl Eugen

I've attached dither_tiny.patch -- it solve the biggest problem when dst_depth > 8 and white goes to black.
If you don't want to loose time for DITHER_COPY problem, please apply only this dither_tiny.patch -- for one iteration it is acceptable quality.

movie after 200 iterations 12bit -> 10bit -> 8bit ->12bit with dither_tiny.patch
msystem.waw.pl/x265/w200.mkv

and the same but with dither_sub.patch
msystem.waw.pl/x265/n200.mkv
libswscale/swscale_unscaled.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index ba3d688..bd4e4f2 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -1488,7 +1488,7 @@  static int packedCopyWrapper(SwsContext *c, const uint8_t *src[],
     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];\
+        const uint8_t *dither= dithers[src_depth-dst_depth-1][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);\