avcodec/flacdec: Attempt to auto-detect old buggy flac
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 17 May 2015 11:10:33 +0000 (13:10 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 17 May 2015 11:42:32 +0000 (13:42 +0200)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/flacdec.c

index 36d2928..30fe416 100644 (file)
@@ -315,6 +315,33 @@ static int decode_subframe_fixed(FLACContext *s, int32_t *decoded,
     return 0;
 }
 
+static void lpc_analyze_remodulate(int32_t *decoded, const int coeffs[32],
+                                   int order, int qlevel, int len, int bps)
+{
+    int i, j;
+    int ebps = 1 << (bps-1);
+    unsigned sigma = 0;
+
+    for (i = order; i < len; i++)
+        sigma |= decoded[i] + ebps;
+
+    if (sigma < 2*ebps)
+        return;
+
+    for (i = len - 1; i >= order; i--) {
+        int64_t p = 0;
+        for (j = 0; j < order; j++)
+            p += coeffs[j] * (int64_t)decoded[i-order+j];
+        decoded[i] -= p >> qlevel;
+    }
+    for (i = order; i < len; i++, decoded++) {
+        int32_t p = 0;
+        for (j = 0; j < order; j++)
+            p += coeffs[j] * (uint32_t)decoded[j];
+        decoded[j] += p >> qlevel;
+    }
+}
+
 static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order,
                                int bps)
 {
@@ -352,6 +379,8 @@ static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order,
         s->dsp.lpc16(decoded, coeffs, pred_order, qlevel, s->blocksize);
     } else {
         s->dsp.lpc32(decoded, coeffs, pred_order, qlevel, s->blocksize);
+        if (s->flac_stream_info.bps <= 16)
+            lpc_analyze_remodulate(decoded, coeffs, pred_order, qlevel, s->blocksize, bps);
     }
 
     return 0;