From c5cd2311518bdd6adff8d76a9aa69db00a5514ec Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Thu, 8 Dec 2011 03:57:21 +0600 Subject: [PATCH] Partially fix CDLMS prediction --- libavcodec/wmalosslessdec.c | 118 ++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 90a2c97fcd..1c2056b2cc 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) { - 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 { + 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 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]; /* 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; + int residue, input; - 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; + 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 */