From 001a74ff53abe4322150bf28d3bc6e8df64b5526 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Sat, 31 Dec 2011 23:47:43 +0600 Subject: [PATCH 1/6] Fix AC filter buffers and AC filter reversion --- libavcodec/wmalosslessdec.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index e520ad3f58..5ecb4241dd 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -231,8 +231,8 @@ typedef struct WmallDecodeCtx { int8_t acfilter_order; int8_t acfilter_scaling; - int acfilter_coeffs[16]; - int acfilter_prevvalues[16]; + int64_t acfilter_coeffs[16]; + int acfilter_prevvalues[2][16]; int8_t mclms_order; int8_t mclms_scaling; @@ -1023,23 +1023,34 @@ static void revert_inter_ch_decorr(WmallDecodeCtx *s, int tile_size) 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 pred; + int i, j; + int64_t *filter_coeffs = s->acfilter_coeffs; 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]; + int *prevvalues = s->acfilter_prevvalues[ich]; + for (i = 0; i < order; i++) { + pred = 0; + for (j = 0; j < order; j++) { + if (i <= j) + pred += filter_coeffs[j] * prevvalues[j - i]; + else + pred += s->channel_residues[ich][i - j - 1] * filter_coeffs[j]; + } pred >>= scaling; - ch_coeffs[ich][icoef] += pred; - for (itap = 1; itap < order; itap++) - prevvalues[itap] = prevvalues[itap - 1]; - prevvalues[0] = ch_coeffs[ich][icoef]; + s->channel_residues[ich][i] += pred; } + for (i = order; i < tile_size; i++) { + pred = 0; + for (j = 0; j < order; j++) + pred += s->channel_residues[ich][i - j - 1] * filter_coeffs[j]; + pred >>= scaling; + s->channel_residues[ich][i] += pred; + } + for (j = 0; j < order; j++) + prevvalues[j] = s->channel_residues[ich][tile_size - j - 1]; } } From 8dc8dd9f6fc0ab556cb12cd4a8c09d72587f8399 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Sat, 31 Dec 2011 23:49:49 +0600 Subject: [PATCH 2/6] Reset acfilter_prevvalues buffer in clear_codec_buffers() --- libavcodec/wmalosslessdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 5ecb4241dd..ae7373abf5 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -752,6 +752,7 @@ static void clear_codec_buffers(WmallDecodeCtx *s) memset(s->acfilter_coeffs, 0, 16 * sizeof(int)); memset(s->lpc_coefs , 0, 40 * 2 * sizeof(int)); + memset(s->acfilter_prevvalues, 0, 16 * 2 * sizeof(int)); // may be wrong memset(s->mclms_coeffs , 0, 128 * sizeof(int16_t)); memset(s->mclms_coeffs_cur, 0, 4 * sizeof(int16_t)); From a6da23f1467122ac2d52edd406870128339dc88a Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Sun, 1 Jan 2012 00:00:51 +0600 Subject: [PATCH 3/6] Cosmetics: Remove two empty lines and realign some code --- libavcodec/wmalosslessdec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index ae7373abf5..da8bb59c8b 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -321,7 +321,6 @@ static void dump_int_buffer(uint8_t *buffer, int size, int length, int delimiter av_log(0, 0, "%d, ", *(int16_t *)(buffer + i * size)); } av_log(0, 0, "\n"); - } /** @@ -750,9 +749,9 @@ static void clear_codec_buffers(WmallDecodeCtx *s) { int ich, ilms; - memset(s->acfilter_coeffs, 0, 16 * sizeof(int)); - memset(s->lpc_coefs , 0, 40 * 2 * sizeof(int)); + memset(s->acfilter_coeffs , 0, 16 * sizeof(int)); memset(s->acfilter_prevvalues, 0, 16 * 2 * sizeof(int)); // may be wrong + memset(s->lpc_coefs , 0, 40 * 2 * sizeof(int)); memset(s->mclms_coeffs , 0, 128 * sizeof(int16_t)); memset(s->mclms_coeffs_cur, 0, 4 * sizeof(int16_t)); From 3d8449512840215ab48d1b2e337bbd0841635300 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Sun, 1 Jan 2012 14:32:10 +0600 Subject: [PATCH 4/6] Use quantizer value read from bitstream Currently the code initializes quantizer even before reading it from bitstream and uses that to dequantize samples. --- libavcodec/wmalosslessdec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index da8bb59c8b..ce845f1e55 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1067,7 +1067,6 @@ static int decode_subframe(WmallDecodeCtx *s) 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); @@ -1194,9 +1193,10 @@ static int decode_subframe(WmallDecodeCtx *s) 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; + if (s->quant_stepsize != 1) + for (i = 0; i < s->num_channels; i++) + for (j = 0; j < subframe_len; j++) + s->channel_residues[i][j] *= s->quant_stepsize; /** handled one subframe */ From f7166f7d8d29033a5c1371fb2340c3ada0889cb7 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Tue, 3 Jan 2012 01:51:17 +0600 Subject: [PATCH 5/6] Suppress dumping of residues buffer --- libavcodec/wmalosslessdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index ce845f1e55..adf9ae90fc 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -719,7 +719,7 @@ static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size) residue = residue >> 1; s->channel_residues[ch][i] = residue; } - dump_int_buffer(s->channel_residues[ch], 4, tile_size, 16); + //dump_int_buffer(s->channel_residues[ch], 4, tile_size, 16); return 0; From 2083a10abff252efc5a54c778e985516d520587a Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Tue, 3 Jan 2012 01:49:00 +0600 Subject: [PATCH 6/6] Fix audio output Up until now, the decoder didn't output anything in the data buffer. This fixes all the issues related to sample format, removes leftover code and actually outputs some audio to data buffer. With this, the only sample we have can be played. Seeking is still broken though. --- libavcodec/wmalosslessdec.c | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index adf9ae90fc..c623f4ee5a 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -200,8 +200,10 @@ typedef struct WmallDecodeCtx { uint32_t frame_num; ///< current frame number (not used for decoding) GetBitContext gb; ///< bitstream reader context int buf_bit_size; ///< buffer size in bits - float* samples; ///< current samplebuffer pointer - float* samples_end; ///< maximum samplebuffer pointer + int16_t* samples_16; ///< current samplebuffer pointer (16-bit) + int16_t* samples_16_end; ///< maximum samplebuffer pointer + int16_t* samples_32; ///< current samplebuffer pointer (24-bit) + int16_t* samples_32_end; ///< maximum samplebuffer pointer uint8_t drc_gain; ///< gain for the DRC tool int8_t skip_frame; ///< skip output step int8_t parsed_all_subframes; ///< all subframes decoded? @@ -357,12 +359,19 @@ static av_cold int decode_init(AVCodecContext *avctx) dsputil_init(&s->dsp, avctx); init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); - avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - if (avctx->extradata_size >= 18) { s->decode_flags = AV_RL16(edata_ptr+14); channel_mask = AV_RL32(edata_ptr+2); s->bits_per_sample = AV_RL16(edata_ptr); + if (s->bits_per_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + else if (s->bits_per_sample == 24) + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + else { + av_log(avctx, AV_LOG_ERROR, "Unknown bit-depth: %d\n", + s->bits_per_sample); + return AVERROR_INVALIDDATA; + } /** dump the extradata */ for (i = 0; i < avctx->extradata_size; i++) dprintf(avctx, "[%x] ", avctx->extradata[i]); @@ -1198,6 +1207,15 @@ static int decode_subframe(WmallDecodeCtx *s) for (j = 0; j < subframe_len; j++) s->channel_residues[i][j] *= s->quant_stepsize; + // Write to proper output buffer depending on bit-depth + for (i = 0; i < subframe_len; i++) + for (j = 0; j < s->num_channels; j++) { + if (s->bits_per_sample == 16) + *s->samples_16++ = (int16_t) s->channel_residues[j][i]; + else + *s->samples_32++ = s->channel_residues[j][i]; + } + /** handled one subframe */ for (i = 0; i < s->channels_for_cur_subframe; i++) { @@ -1224,9 +1242,14 @@ static int decode_frame(WmallDecodeCtx *s) int more_frames = 0; int len = 0; int i; + int buffer_len; /** check for potential output buffer overflow */ - if (s->num_channels * s->samples_per_frame > s->samples_end - s->samples) { + if (s->bits_per_sample == 16) + buffer_len = s->samples_16_end - s->samples_16; + else + buffer_len = s->samples_32_end - s->samples_32; + if (s->num_channels * s->samples_per_frame > buffer_len) { /** return an error if no frame could be decoded at all */ av_log(s->avctx, AV_LOG_ERROR, "not enough space for the output samples\n"); @@ -1288,8 +1311,7 @@ static int decode_frame(WmallDecodeCtx *s) if (s->skip_frame) { s->skip_frame = 0; - } else - s->samples += s->num_channels * s->samples_per_frame; + } if (s->len_prefix) { if (len != (get_bits_count(gb) - s->frame_offset) + 2) { @@ -1398,8 +1420,13 @@ static int decode_packet(AVCodecContext *avctx, int num_bits_prev_frame; int packet_sequence_number; - s->samples = data; - s->samples_end = (float*)((int8_t*)data + *data_size); + if (s->bits_per_sample == 16) { + s->samples_16 = (int16_t *) data; + s->samples_16_end = (int16_t *) ((int8_t*)data + *data_size); + } else { + s->samples_32 = (int *) data; + s->samples_32_end = (int *) ((int8_t*)data + *data_size);; + } *data_size = 0; if (s->packet_done || s->packet_loss) { @@ -1492,7 +1519,10 @@ static int decode_packet(AVCodecContext *avctx, save_bits(s, gb, remaining_bits(s, gb), 0); } - *data_size = 0; // (int8_t *)s->samples - (int8_t *)data; + if (s->bits_per_sample == 16) + *data_size = (int8_t *)s->samples_16 - (int8_t *)data; + else + *data_size = (int8_t *)s->samples_32 - (int8_t *)data; s->packet_offset = get_bits_count(gb) & 7; return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;