Bink: clip AC coefficients during dequantization.
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>
Sun, 17 Jul 2011 11:03:57 +0000 (13:03 +0200)
committerCarl Eugen Hoyos <cehoyos@ag.or.at>
Thu, 4 Aug 2011 09:42:33 +0000 (11:42 +0200)
Fixes artefacts with Neverwinter Nights WOTCLogo.bik
(http://drmccoy.de/zeugs/WOTCLogo.bik).
Fixes trac ticket #352.

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
(cherry picked from commit 47b71eea099b3fe2c7e16644878ad9b7067974e3)

libavcodec/bink.c

index ef07747..4328a43 100644 (file)
@@ -571,6 +571,22 @@ static inline int binkb_get_value(BinkContext *c, int bundle_num)
     return ret;
 }
 
+static inline DCTELEM dequant(DCTELEM in, uint32_t quant, int dc)
+{
+    /* Note: multiplication is unsigned but we want signed shift
+     * otherwise clipping breaks.
+     * TODO: The official decoder does not use clipping at all
+     * but instead uses the full 32-bit result.
+     * However clipping at least gets rid of the case that a
+     * half-black half-white intra block gets black and white swapped
+     * and should cause at most minor differences (except for DC). */
+    int32_t res = in * quant;
+    res >>= 11;
+    if (!dc)
+        res = av_clip_int16(res);
+    return res;
+}
+
 /**
  * Read 8x8 block of DCT coefficients.
  *
@@ -669,10 +685,10 @@ static int read_dct_coeffs(GetBitContext *gb, DCTELEM block[64], const uint8_t *
 
     quant = quant_matrices[quant_idx];
 
-    block[0] = (block[0] * quant[0]) >> 11;
+    block[0] = dequant(block[0], quant[0], 1);
     for (i = 0; i < coef_count; i++) {
         int idx = coef_idx[i];
-        block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11;
+        block[scan[idx]] = dequant(block[scan[idx]], quant[idx], 0);
     }
 
     return 0;