summaryrefslogtreecommitdiff
path: root/libavcodec/wmalosslessdec.c
diff options
context:
space:
mode:
authorMashiat Sarker Shakkhar <shahriman_ams@yahoo.com>2011-11-30 22:41:12 +0600
committerMashiat Sarker Shakkhar <shahriman_ams@yahoo.com>2011-11-30 22:44:59 +0600
commit8aa831c07b47c4f384919cd38930ac64ce04b05b (patch)
tree2a8211c5b1c018fa230126cfa17e91ef2ef942e5 /libavcodec/wmalosslessdec.c
parentbf8715719a3ec85010e7f909c0cdafb265f50fea (diff)
Implement revert_mclms() and associated functions
Diffstat (limited to 'libavcodec/wmalosslessdec.c')
-rw-r--r--libavcodec/wmalosslessdec.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 2a0789bdf0..795fcaed47 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -786,6 +786,93 @@ 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)
{
int16_t pred = 0, icoef;