Merge remote-tracking branch 'shariman/wmall'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 7 Dec 2011 23:37:55 +0000 (00:37 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 7 Dec 2011 23:37:55 +0000 (00:37 +0100)
* shariman/wmall:
  Partially fix CDLMS prediction

Conflicts:
libavcodec/wmalosslessdec.c

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

index 09e8a8e4fdcd69efb25d94330efdc4811810f3f3..03fbb1fdb835525302ccd965db0f8aa62586b4ee 100644 (file)
@@ -776,11 +776,12 @@ 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 - 1;
+            s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order;
         /* 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;
         s->transient[ich] = 1;
+        s->transient_pos[ich] = 0;
     }
 }
 
@@ -875,7 +876,7 @@ static void revert_mclms(WmallDecodeCtx *s, int tile_size)
 
 static int lms_predict(WmallDecodeCtx *s, int ich, int ilms)
 {
-    int16_t pred = 0;
+    int pred = 0;
     int icoef;
     int recent = s->cdlms[ich][ilms].recent;
 
@@ -883,39 +884,53 @@ static int lms_predict(WmallDecodeCtx *s, int ich, int ilms)
         pred += s->cdlms[ich][ilms].coefs[icoef] *
                     s->cdlms[ich][ilms].lms_prevvalues[icoef + recent];
 
-    pred += (1 << (s->cdlms[ich][ilms].scaling - 1));
+    //pred += (1 << (s->cdlms[ich][ilms].scaling - 1));
     /* XXX: Table 29 has:
             iPred >= cdlms[iCh][ilms].scaling;
        seems to me like a missing > */
-    pred >>= s->cdlms[ich][ilms].scaling;
+    //pred >>= s->cdlms[ich][ilms].scaling;
     return pred;
 }
 
-static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int16_t residue, int16_t pred)
+static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input, int residue)
 {
-    int16_t icoef;
+    int icoef;
     int recent = s->cdlms[ich][ilms].recent;
-    int16_t range = (1 << s->bits_per_sample - 1) - 1;
+    int range = 1 << s->bits_per_sample - 1;
     int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample
-    int16_t input = residue + pred;
 
-    if (residue > 0) {
+    if (residue < 0) {
         for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
-            s->cdlms[ich][ilms].coefs[icoef] +=
+            s->cdlms[ich][ilms].coefs[icoef] -=
                 s->cdlms[ich][ilms].lms_updates[icoef + recent];
-    } else {
+    } else if (residue > 0) {
         for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
-            s->cdlms[ich][ilms].coefs[icoef] -=
+            s->cdlms[ich][ilms].coefs[icoef] +=
                 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);
 
-    if (input > pred)
-        s->cdlms[ich][ilms].lms_updates[recent] = s->update_speed[ich];
-    else if (input < pred)
+    if (recent)
+        recent--;
+    else {
+        /* XXX: This memcpy()s will probably fail if a fixed 32-bit buffer is used.
+                follow kshishkov's suggestion of using a union. */
+        memcpy(&s->cdlms[ich][ilms].lms_prevvalues[s->cdlms[ich][ilms].order],
+               s->cdlms[ich][ilms].lms_prevvalues,
+               bps * s->cdlms[ich][ilms].order);
+        memcpy(&s->cdlms[ich][ilms].lms_updates[s->cdlms[ich][ilms].order],
+               s->cdlms[ich][ilms].lms_updates,
+               bps * s->cdlms[ich][ilms].order);
+        recent = s->cdlms[ich][ilms].order - 1;
+    }
+
+    s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1);
+    if (!input)
+        s->cdlms[ich][ilms].lms_updates[recent] = 0;
+    else if (input < 0)
         s->cdlms[ich][ilms].lms_updates[recent] = -s->update_speed[ich];
+    else
+        s->cdlms[ich][ilms].lms_updates[recent] = s->update_speed[ich];
 
     /* XXX: spec says:
     cdlms[iCh][ilms].updates[iRecent + cdlms[iCh][ilms].order >> 4] >>= 2;
@@ -925,21 +940,9 @@ static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int16_t residue, in
         seperate buffers? Here I've assumed that the two are same which makes
         more sense to me.
     */
-    s->cdlms[ich][ilms].lms_updates[recent + s->cdlms[ich][ilms].order >> 4] >>= 2;
-    s->cdlms[ich][ilms].lms_updates[recent + s->cdlms[ich][ilms].order >> 3] >>= 1;
-    /* XXX: recent + (s->cdlms[ich][ilms].order >> 4) ? */
-
-    if (s->cdlms[ich][ilms].recent == 0) {
-        /* XXX: This memcpy()s will probably fail if a fixed 32-bit buffer is used.
-                follow kshishkov's suggestion of using a union. */
-        memcpy(s->cdlms[ich][ilms].lms_prevvalues + s->cdlms[ich][ilms].order,
-               s->cdlms[ich][ilms].lms_prevvalues,
-               bps * s->cdlms[ich][ilms].order);
-        memcpy(s->cdlms[ich][ilms].lms_updates + s->cdlms[ich][ilms].order,
-               s->cdlms[ich][ilms].lms_updates,
-               bps * s->cdlms[ich][ilms].order);
-        s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order;
-    }
+    s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 4)] >>= 2;
+    s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 3)] >>= 1;
+    s->cdlms[ich][ilms].recent = recent;
 }
 
 static void use_high_update_speed(WmallDecodeCtx *s, int ich)
@@ -974,33 +977,23 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich)
     }
 }
 
-static void revert_cdlms(WmallDecodeCtx *s, int tile_size)
+static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end)
 {
-    int icoef, ich;
-    int16_t pred, channel_coeff;
+    int icoef;
+    int pred;
     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++) {
-            channel_coeff = s->channel_residues[ich][icoef];
-            if (icoef == s->transient_pos[ich]) {
-                s->transient[ich] = 1;
-                use_high_update_speed(s, ich);
-            }
-            for (ilms = num_lms - 1; ilms >= 0; ilms--) {
-                pred = lms_predict(s, ich, ilms);
-                lms_update(s, ich, ilms, channel_coeff, pred);
-                channel_coeff += pred;
-            }
-            if (s->transient[ich]) {
-                --s->channel[ich].transient_counter;
-                if(!s->channel[ich].transient_counter)
-                    use_normal_update_speed(s, ich);
-            }
-            s->channel_coeffs[ich][icoef] = channel_coeff;
+    int residue, input;
+
+    num_lms = s->cdlms_ttl[ch];
+    for (ilms = num_lms - 1; ilms >= 0; ilms--) {
+        //s->cdlms[ch][ilms].recent = s->cdlms[ch][ilms].order;
+        for (icoef = coef_begin; icoef < coef_end; icoef++) {
+            pred = 1 << (s->cdlms[ch][ilms].scaling - 1);
+            residue = s->channel_residues[ch][icoef];
+            pred += lms_predict(s, ch, ilms);
+            input = residue + (pred >> s->cdlms[ch][ilms].scaling);
+            lms_update(s, ch, ilms, input, residue);
+            s->channel_residues[ch][icoef] = input;
         }
     }
 }
@@ -1130,10 +1123,15 @@ static int decode_subframe(WmallDecodeCtx *s)
         }
     } else {
         for(i = 0; i < s->num_channels; i++)
-            if(s->is_channel_coded[i])
-                decode_channel_residues(s, i, subframe_len);
+            if(s->is_channel_coded[i]) {
+            decode_channel_residues(s, i, subframe_len);
+            if (s->seekable_tile)
+                use_high_update_speed(s, i);
+            else
+                use_normal_update_speed(s, i);
+            revert_cdlms(s, i, 0, subframe_len);
+        }
     }
-    revert_cdlms(s, subframe_len);
 
     /** handled one subframe */