Fix inverse-MCLMS filtering routines
authorMashiat Sarker Shakkhar <shahriman_ams@yahoo.com>
Thu, 22 Dec 2011 17:48:02 +0000 (23:48 +0600)
committerMashiat Sarker Shakkhar <shahriman_ams@yahoo.com>
Thu, 22 Dec 2011 17:48:02 +0000 (23:48 +0600)
libavcodec/wmalosslessdec.c

index c61e396..29dce56 100644 (file)
@@ -787,36 +787,35 @@ static void reset_codec(WmallDecodeCtx *s)
 
 
 
-static void mclms_update(WmallDecodeCtx *s, int icoef)
+static void mclms_update(WmallDecodeCtx *s, int icoef, int *pred)
 {
     int i, j, ich;
-    int16_t pred_error;
+    int pred_error;
     int order = s->mclms_order;
     int num_channels = s->num_channels;
-    int16_t range = 1 << (s->bits_per_sample - 1);
+    int range = 1 << (s->bits_per_sample - 1);
     int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample
 
     for (ich = 0; ich < num_channels; ich++) {
-        pred_error = s->channel_coeffs[ich][icoef] -
-                     s->channel_residues[ich][icoef];
+        pred_error = s->channel_residues[ich][icoef] - pred[ich];
         if (pred_error > 0) {
             for (i = 0; i < order * num_channels; i++)
                 s->mclms_coeffs[i + ich * order * num_channels] +=
                     s->mclms_updates[s->mclms_recent + i];
-            for (j = 0; j < i; j++) {
-                if (s->channel_coeffs[ich][icoef] > 0)
+            for (j = 0; j < ich; j++) {
+                if (s->channel_residues[j][icoef] > 0)
                     s->mclms_coeffs_cur[ich * num_channels + j] += 1;
-                else if (s->channel_coeffs[ich][icoef] < 0)
+                else if (s->channel_residues[j][icoef] < 0)
                     s->mclms_coeffs_cur[ich * num_channels + j] -= 1;
             }
         } else if (pred_error < 0) {
             for (i = 0; i < order * num_channels; i++)
                 s->mclms_coeffs[i + ich * order * num_channels] -=
                     s->mclms_updates[s->mclms_recent + i];
-            for (j = 0; j < i; j++) {
-                if (s->channel_coeffs[ich][icoef] > 0)
+            for (j = 0; j < ich; j++) {
+                if (s->channel_residues[j][icoef] > 0)
                     s->mclms_coeffs_cur[ich * num_channels + j] -= 1;
-                else if (s->channel_coeffs[ich][icoef] < 0)
+                else if (s->channel_residues[j][icoef] < 0)
                     s->mclms_coeffs_cur[ich * num_channels + j] += 1;
             }
         }
@@ -824,13 +823,17 @@ static void mclms_update(WmallDecodeCtx *s, int icoef)
 
     for (ich = num_channels - 1; ich >= 0; ich--) {
         s->mclms_recent--;
-        if (s->channel_coeffs[ich][icoef] > range - 1)
+        s->mclms_prevvalues[s->mclms_recent] = s->channel_residues[ich][icoef];
+        if (s->channel_residues[ich][icoef] > range - 1)
             s->mclms_prevvalues[s->mclms_recent] = range - 1;
-        else if (s->channel_coeffs[ich][icoef] <= -range)
+        else if (s->channel_residues[ich][icoef] < -range)
             s->mclms_prevvalues[s->mclms_recent] = -range;
 
-        s->mclms_updates[s->mclms_recent] =
-            av_clip(-1, s->channel_coeffs[ich][icoef], 1);
+        s->mclms_updates[s->mclms_recent] = 0;
+        if (s->channel_residues[ich][icoef] > 0)
+            s->mclms_updates[s->mclms_recent] = 1;
+        else if (s->channel_residues[ich][icoef] < 0)
+            s->mclms_updates[s->mclms_recent] = -1;
     }
 
     if (s->mclms_recent == 0) {
@@ -843,34 +846,35 @@ static void mclms_update(WmallDecodeCtx *s, int icoef)
         s->mclms_recent = num_channels * order;
     }
 }
-static void mclms_predict(WmallDecodeCtx *s, int icoef)
+
+static void mclms_predict(WmallDecodeCtx *s, int icoef, int *pred)
 {
     int ich, i;
-    int16_t pred;
     int order = s->mclms_order;
     int num_channels = s->num_channels;
 
     for (ich = 0; ich < num_channels; ich++) {
         if (!s->is_channel_coded[ich])
             continue;
-        pred = 0;
+        pred[ich] = 0;
         for (i = 0; i < order * num_channels; i++)
-            pred += s->mclms_prevvalues[i] *
-                    s->mclms_coeffs[i + order * num_channels * ich];
+            pred[ich] += s->mclms_prevvalues[i + s->mclms_recent] *
+                         s->mclms_coeffs[i + order * num_channels * ich];
         for (i = 0; i < ich; i++)
-            pred += s->channel_coeffs[ich][icoef] *
-                    s->mclms_coeffs_cur[i + order * num_channels * ich];
-        s->channel_coeffs[ich][icoef] =
-                    s->channel_residues[ich][icoef] + pred;
+            pred[ich] += s->channel_residues[i][icoef] *
+                         s->mclms_coeffs_cur[i + num_channels * ich];
+        pred[ich] += 1 << s->mclms_scaling - 1;
+        pred[ich] >>= s->mclms_scaling;
+        s->channel_residues[ich][icoef] += pred[ich];
     }
 }
 
 static void revert_mclms(WmallDecodeCtx *s, int tile_size)
 {
-    int icoef;
+    int icoef, pred[s->num_channels];
     for (icoef = 0; icoef < tile_size; icoef++) {
-        mclms_predict(s, icoef);
-        mclms_update(s, icoef);
+        mclms_predict(s, icoef, pred);
+        mclms_update(s, icoef, pred);
     }
 }