diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 0af01de390..76dc6c99a8 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -232,6 +232,7 @@ typedef struct WmallDecodeCtx { int8_t acfilter_order; int8_t acfilter_scaling; int acfilter_coeffs[16]; + int acfilter_prevvalues[16]; int8_t mclms_order; int8_t mclms_scaling; @@ -279,7 +280,7 @@ typedef struct WmallDecodeCtx { int lpc_scaling; int lpc_intbits; - int16_t channel_coeffs[2][2048]; // FIXME: should be 32-bit / 16-bit depending on bit-depth + int channel_coeffs[2][2048]; // FIXME: should be 32-bit / 16-bit depending on bit-depth } WmallDecodeCtx; @@ -787,36 +788,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 +824,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 +847,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); } } @@ -948,9 +953,10 @@ static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input, int resi static void use_high_update_speed(WmallDecodeCtx *s, int ich) { int ilms, recent, icoef; - s->update_speed[ich] = 16; for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) { recent = s->cdlms[ich][ilms].recent; + if (s->update_speed[ich] == 16) + continue; if (s->bV3RTM) { for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) s->cdlms[ich][ilms].lms_updates[icoef + recent] *= 2; @@ -959,14 +965,16 @@ static void use_high_update_speed(WmallDecodeCtx *s, int ich) s->cdlms[ich][ilms].lms_updates[icoef] *= 2; } } + s->update_speed[ich] = 16; } static void use_normal_update_speed(WmallDecodeCtx *s, int ich) { int ilms, recent, icoef; - s->update_speed[ich] = 8; for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) { recent = s->cdlms[ich][ilms].recent; + if (s->update_speed[ich] == 8) + continue; if (s->bV3RTM) { for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) s->cdlms[ich][ilms].lms_updates[icoef + recent] /= 2; @@ -975,6 +983,7 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich) s->cdlms[ich][ilms].lms_updates[icoef] /= 2; } } + s->update_speed[ich] = 8; } static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end) @@ -998,7 +1007,41 @@ static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end } } +static void revert_inter_ch_decorr(WmallDecodeCtx *s, int tile_size) +{ + int icoef; + if (s->num_channels != 2) + return; + else { + for (icoef = 0; icoef < tile_size; icoef++) { + s->channel_residues[0][icoef] -= s->channel_residues[1][icoef] >> 1; + s->channel_residues[1][icoef] += s->channel_residues[0][icoef]; + } + } +} +static void revert_acfilter(WmallDecodeCtx *s, int tile_size) +{ + int ich, icoef; + int pred = 0, itap; + int **ch_coeffs = s->channel_residues; + int *filter_coeffs = s->acfilter_coeffs; + int *prevvalues = s->acfilter_prevvalues; + int scaling = s->acfilter_scaling; + int order = s->acfilter_order; + + for (ich = 0; ich < s->num_channels; ich++) { + for (icoef = 0; icoef < tile_size; icoef++) { + for (itap = 0; itap < order; itap++) + pred += filter_coeffs[itap] * prevvalues[itap]; + pred >>= scaling; + ch_coeffs[ich][icoef] += pred; + for (itap = 1; itap < order; itap++) + prevvalues[itap] = prevvalues[itap - 1]; + prevvalues[0] = ch_coeffs[ich][icoef]; + } + } +} /** *@brief Decode a single subframe (block). @@ -1009,10 +1052,11 @@ static int decode_subframe(WmallDecodeCtx *s) { int offset = s->samples_per_frame; int subframe_len = s->samples_per_frame; - int i; + int i, j; int total_samples = s->samples_per_frame * s->num_channels; int rawpcm_tile; int padding_zeroes; + int quant_stepsize = s->quant_stepsize; s->subframe_offset = get_bits_count(&s->gb); @@ -1112,7 +1156,6 @@ static int decode_subframe(WmallDecodeCtx *s) if(rawpcm_tile) { int bits = s->bits_per_sample - padding_zeroes; - int j; dprintf(s->avctx, "RAWPCM %d bits per sample. total %d bits, remain=%d\n", bits, bits * s->num_channels * subframe_len, get_bits_count(&s->gb)); for(i = 0; i < s->num_channels; i++) { @@ -1132,6 +1175,17 @@ static int decode_subframe(WmallDecodeCtx *s) revert_cdlms(s, i, 0, subframe_len); } } + if (s->do_mclms) + revert_mclms(s, subframe_len); + if (s->do_inter_ch_decorr) + revert_inter_ch_decorr(s, subframe_len); + if(s->do_ac_filter) + revert_acfilter(s, subframe_len); + + /* Dequantize */ + for (i = 0; i < s->num_channels; i++) + for (j = 0; j < subframe_len; j++) + s->channel_residues[i][j] *= quant_stepsize; /** handled one subframe */