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;