Merge remote-tracking branch 'shariman/wmall'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 7 Dec 2011 03:49:42 +0000 (04:49 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 7 Dec 2011 03:49:42 +0000 (04:49 +0100)
* shariman/wmall:
  Fix lms_update()
  Move num_lms reading out of a loop
  Use correct value for range
  Fix some int / int16_t / int32_t confusion
  Implement revert_mclms() and associated functions
  Fix two more int16_t vs. int confusion
  Init s->cdlms[][].recent to order - 1
  Add a size argument to dump_int_buffer()
  Get rid of logging that are not required anymore
  Fix some int vs. int16_t confusion

Conflicts:
libavcodec/wmalosslessdec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/wmalosslessdec.c

index 514cd0758c3f6252554652c976d8450069a20b97..09e8a8e4fdcd69efb25d94330efdc4811810f3f3 100644 (file)
@@ -237,7 +237,7 @@ typedef struct WmallDecodeCtx {
     int8_t mclms_scaling;
     int16_t mclms_coeffs[128];
     int16_t mclms_coeffs_cur[4];
-    int mclms_prevvalues[64];   // FIXME: should be 32-bit / 16-bit depending on bit-depth
+    int16_t mclms_prevvalues[64];   // FIXME: should be 32-bit / 16-bit depending on bit-depth
     int16_t mclms_updates[64];
     int mclms_recent;
 
@@ -250,7 +250,7 @@ typedef struct WmallDecodeCtx {
         int coefsend;
         int bitsend;
         int16_t coefs[256];
-    int lms_prevvalues[512];    // FIXME: see above
+    int16_t lms_prevvalues[512];    // FIXME: see above
     int16_t lms_updates[512];   // and here too
     int recent;
     } cdlms[2][9];              /* XXX: Here, 2 is the max. no. of channels allowed,
@@ -279,7 +279,7 @@ typedef struct WmallDecodeCtx {
     int lpc_scaling;
     int lpc_intbits;
 
-    int channel_coeffs[2][2048];
+    int16_t channel_coeffs[2][2048]; // FIXME: should be 32-bit / 16-bit depending on bit-depth
 
 } WmallDecodeCtx;
 
@@ -289,6 +289,8 @@ typedef struct WmallDecodeCtx {
 
 
 static int num_logged_tiles = 0;
+static int num_logged_subframes = 0;
+static int num_lms_update_call = 0;
 
 /**
  *@brief helper function to print the most important members of the context
@@ -308,14 +310,14 @@ static void av_cold dump_context(WmallDecodeCtx *s)
     PRINT("num channels",        s->num_channels);
 }
 
-static void dump_int_buffer(int *buffer, int length, int delimiter)
+static void dump_int_buffer(uint8_t *buffer, int size, int length, int delimiter)
 {
     int i;
 
     for (i=0 ; i<length ; i++) {
         if (!(i%delimiter))
             av_log(0, 0, "\n[%d] ", i);
-        av_log(0, 0, "%d, ", buffer[i]);
+        av_log(0, 0, "%d, ", *(int16_t *)(buffer + i * size));
     }
     av_log(0, 0, "\n");
 
@@ -716,11 +718,8 @@ static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size)
         else
             residue = residue >> 1;
         s->channel_residues[ch][i] = residue;
-
-    /*if (num_logged_tiles < 1)
-        av_log(0, 0, "%4d ", residue); */
     }
-    dump_int_buffer(s->channel_residues[ch], tile_size, 16);
+    dump_int_buffer(s->channel_residues[ch], 4, tile_size, 16);
 
     return 0;
 
@@ -761,7 +760,7 @@ static void clear_codec_buffers(WmallDecodeCtx *s)
     for (ich = 0; ich < s->num_channels; ich++) {
         for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++) {
             memset(s->cdlms[ich][ilms].coefs         , 0, 256 * sizeof(int16_t));
-            memset(s->cdlms[ich][ilms].lms_prevvalues, 0, 512 * sizeof(int));
+            memset(s->cdlms[ich][ilms].lms_prevvalues, 0, 512 * sizeof(int16_t));
             memset(s->cdlms[ich][ilms].lms_updates   , 0, 512 * sizeof(int16_t));
         }
         s->ave_sum[ich] = 0;
@@ -777,7 +776,7 @@ static void reset_codec(WmallDecodeCtx *s)
     s->mclms_recent = s->mclms_order * s->num_channels;
     for (ich = 0; ich < s->num_channels; ich++) {
         for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++)
-            s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order;
+            s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order - 1;
         /* first sample of a seekable subframe is considered as the starting of
            a transient area which is samples_per_frame samples long */
         s->channel[ich].transient_counter = s->samples_per_frame;
@@ -787,9 +786,97 @@ static void reset_codec(WmallDecodeCtx *s)
 
 
 
+static void mclms_update(WmallDecodeCtx *s, int icoef)
+{
+    int i, j, ich;
+    int16_t pred_error;
+    int order = s->mclms_order;
+    int num_channels = s->num_channels;
+    int16_t 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];
+        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)
+                    s->mclms_coeffs_cur[ich * num_channels + j] += 1;
+                else if (s->channel_coeffs[ich][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)
+                    s->mclms_coeffs_cur[ich * num_channels + j] -= 1;
+                else if (s->channel_coeffs[ich][icoef] < 0)
+                    s->mclms_coeffs_cur[ich * num_channels + j] += 1;
+            }
+        }
+    }
+
+    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] = range - 1;
+        else if (s->channel_coeffs[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);
+    }
+
+    if (s->mclms_recent == 0) {
+        memcpy(s->mclms_prevvalues[order * num_channels],
+               s->mclms_prevvalues,
+               bps * order * num_channels);
+        memcpy(s->mclms_updates[order * num_channels],
+               s->mclms_updates,
+               bps * order * num_channels);
+        s->mclms_recent = num_channels * order;
+    }
+}
+static void mclms_predict(WmallDecodeCtx *s, int icoef)
+{
+    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;
+        for (i = 0; i < order * num_channels; i++)
+            pred += s->mclms_prevvalues[i] *
+                    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;
+    }
+}
+
+static void revert_mclms(WmallDecodeCtx *s, int tile_size)
+{
+    int icoef;
+    for (icoef = 0; icoef < tile_size; icoef++) {
+        mclms_predict(s, icoef);
+        mclms_update(s, icoef);
+    }
+}
+
 static int lms_predict(WmallDecodeCtx *s, int ich, int ilms)
 {
-    int32_t pred = 0, icoef;
+    int16_t pred = 0;
+    int icoef;
     int recent = s->cdlms[ich][ilms].recent;
 
     for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
@@ -804,21 +891,23 @@ static int lms_predict(WmallDecodeCtx *s, int ich, int ilms)
     return pred;
 }
 
-static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int32_t input, int32_t pred)
+static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int16_t residue, int16_t pred)
 {
-    int icoef;
+    int16_t icoef;
     int recent = s->cdlms[ich][ilms].recent;
-    int range = 1 << (s->bits_per_sample - 1);
+    int16_t range = (1 << s->bits_per_sample - 1) - 1;
     int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample
+    int16_t input = residue + pred;
 
-    if (input > pred) {
+    if (residue > 0) {
         for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
             s->cdlms[ich][ilms].coefs[icoef] +=
                 s->cdlms[ich][ilms].lms_updates[icoef + recent];
     } else {
         for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
             s->cdlms[ich][ilms].coefs[icoef] -=
-                s->cdlms[ich][ilms].lms_updates[icoef];     // XXX: [icoef + recent] ?
+                s->cdlms[ich][ilms].lms_updates[icoef + recent];    /* spec mistakenly
+                                                                    dropped the recent */
     }
     s->cdlms[ich][ilms].recent--;
     s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1);
@@ -888,14 +977,14 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich)
 static void revert_cdlms(WmallDecodeCtx *s, int tile_size)
 {
     int icoef, ich;
-    int32_t pred, channel_coeff;
+    int16_t pred, channel_coeff;
     int ilms, num_lms;
 
     for (ich = 0; ich < s->num_channels; ich++) {
         if (!s->is_channel_coded[ich])
             continue;
+        num_lms = s->cdlms_ttl[ich];
         for (icoef = 0; icoef < tile_size; icoef++) {
-            num_lms = s->cdlms_ttl[ich];
             channel_coeff = s->channel_residues[ich][icoef];
             if (icoef == s->transient_pos[ich]) {
                 s->transient[ich] = 1;
@@ -903,8 +992,8 @@ static void revert_cdlms(WmallDecodeCtx *s, int tile_size)
             }
             for (ilms = num_lms - 1; ilms >= 0; ilms--) {
                 pred = lms_predict(s, ich, ilms);
-                channel_coeff += pred;
                 lms_update(s, ich, ilms, channel_coeff, pred);
+                channel_coeff += pred;
             }
             if (s->transient[ich]) {
                 --s->channel[ich].transient_counter;
@@ -1056,6 +1145,7 @@ static int decode_subframe(WmallDecodeCtx *s)
         }
         ++s->channel[c].cur_subframe;
     }
+    num_logged_subframes++;
     return 0;
 }