[FFmpeg-cvslog] Partially fix CDLMS prediction

Mashiat Sarker Shakkhar git at videolan.org
Thu Dec 8 00:44:59 CET 2011


ffmpeg | branch: master | Mashiat Sarker Shakkhar <shahriman_ams at yahoo.com> | Thu Dec  8 03:57:21 2011 +0600| [c5cd2311518bdd6adff8d76a9aa69db00a5514ec] | committer: Mashiat Sarker Shakkhar

Partially fix CDLMS prediction

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c5cd2311518bdd6adff8d76a9aa69db00a5514ec
---

 libavcodec/wmalosslessdec.c |  118 +++++++++++++++++++++----------------------
 1 files changed, 58 insertions(+), 60 deletions(-)

diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 90a2c97..1c2056b 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -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 */
 



More information about the ffmpeg-cvslog mailing list