X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fwmadec.c;h=a7300594ca3c2ba9f33bb8221f5985a2a4eb8100;hb=ed7bdd8647a3d0f534c2af0d244fc8744ff262a0;hp=03d7bd19fcf159a90af8ef113a6705dde7351fe2;hpb=9d06d7bce3babb82ed650c13ed13a57f6f626a71;p=ffmpeg diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 03d7bd19fcf..a7300594ca3 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -1,21 +1,21 @@ /* * WMA compatible decoder - * Copyright (c) 2002 The FFmpeg Project + * Copyright (c) 2002 The Libav Project * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -124,6 +124,10 @@ static int wma_decode_init(AVCodecContext * avctx) } avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; + return 0; } @@ -178,15 +182,6 @@ static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) s->lsp_pow_m_table2[i] = b - a; b = a; } -#if 0 - for(i=1;i<20;i++) { - float v, r1, r2; - v = 5.0 / i; - r1 = pow_m1_4(s, v); - r2 = pow(v,-0.25); - printf("%f^-0.25=%f e=%f\n", v, r1, r2 - r1); - } -#endif } /** @@ -361,7 +356,7 @@ static int decode_exp_vlc(WMACodecContext *s, int ch) } /* NOTE: this offset is the same as MPEG4 AAC ! */ last_exp += code - 60; - if ((unsigned)last_exp + 60 > FF_ARRAY_ELEMS(pow_tab)) { + if ((unsigned)last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) { av_log(s->avctx, AV_LOG_ERROR, "Exponent out of range: %d\n", last_exp); return -1; @@ -447,6 +442,7 @@ static int wma_decode_block(WMACodecContext *s) int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; float mdct_norm; + FFTContext *mdct; #ifdef TRACE tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); @@ -742,12 +738,14 @@ static int wma_decode_block(WMACodecContext *s) } next: + mdct = &s->mdct_ctx[bsize]; + for(ch = 0; ch < s->nb_channels; ch++) { int n4, index; n4 = s->block_len / 2; if(s->channel_coded[ch]){ - ff_imdct_calc(&s->mdct_ctx[bsize], s->output, s->coefs[ch]); + mdct->imdct_calc(mdct, s->output, s->coefs[ch]); }else if(!(s->ms_stereo && ch==1)) memset(s->output, 0, sizeof(s->output)); @@ -789,13 +787,13 @@ static int wma_decode_frame(WMACodecContext *s, int16_t *samples) /* convert frame to integer */ n = s->frame_len; incr = s->nb_channels; - for (ch = 0; ch < MAX_CHANNELS; ch++) - output[ch] = s->frame_out[ch]; - s->dsp.float_to_int16_interleave(samples, output, n, incr); - for(ch = 0; ch < incr; ch++) { - /* prepare for next block */ - memmove(&s->frame_out[ch][0], &s->frame_out[ch][n], n * sizeof(float)); - } + for (ch = 0; ch < MAX_CHANNELS; ch++) + output[ch] = s->frame_out[ch]; + s->fmt_conv.float_to_int16_interleave(samples, output, n, incr); + for (ch = 0; ch < incr; ch++) { + /* prepare for next block */ + memmove(&s->frame_out[ch][0], &s->frame_out[ch][n], n * sizeof(float)); + } #ifdef TRACE dump_shorts(s, "samples", samples, n * s->nb_channels); @@ -803,14 +801,13 @@ static int wma_decode_frame(WMACodecContext *s, int16_t *samples) return 0; } -static int wma_decode_superframe(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +static int wma_decode_superframe(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; WMACodecContext *s = avctx->priv_data; - int nb_frames, bit_offset, i, pos, len; + int nb_frames, bit_offset, i, pos, len, ret; uint8_t *q; int16_t *samples; @@ -820,25 +817,40 @@ static int wma_decode_superframe(AVCodecContext *avctx, s->last_superframe_len = 0; return 0; } - if (buf_size < s->block_align) - return 0; + if (buf_size < s->block_align) { + av_log(avctx, AV_LOG_ERROR, + "Input packet size too small (%d < %d)\n", + buf_size, s->block_align); + return AVERROR_INVALIDDATA; + } buf_size = s->block_align; - samples = data; - init_get_bits(&s->gb, buf, buf_size*8); if (s->use_bit_reservoir) { /* read super frame header */ skip_bits(&s->gb, 4); /* super frame index */ - nb_frames = get_bits(&s->gb, 4) - 1; + nb_frames = get_bits(&s->gb, 4) - (s->last_superframe_len <= 0); + } else { + nb_frames = 1; + } - if((nb_frames+1) * s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ - av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); - goto fail; - } + /* get output buffer */ + s->frame.nb_samples = nb_frames * s->frame_len; + if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + samples = (int16_t *)s->frame.data[0]; + if (s->use_bit_reservoir) { bit_offset = get_bits(&s->gb, s->byte_offset_bits + 3); + if (bit_offset > get_bits_left(&s->gb)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid last frame bit offset %d > buf size %d (%d)\n", + bit_offset, get_bits_left(&s->gb), buf_size); + goto fail; + } if (s->last_superframe_len > 0) { // printf("skip=%d\n", s->last_bitoffset); @@ -855,9 +867,10 @@ static int wma_decode_superframe(AVCodecContext *avctx, if (len > 0) { *q++ = (get_bits)(&s->gb, len) << (8 - len); } + memset(q, 0, FF_INPUT_BUFFER_PADDING_SIZE); /* XXX: bit_offset bits into last frame */ - init_get_bits(&s->gb, s->last_superframe, MAX_CODED_SUPERFRAME_SIZE*8); + init_get_bits(&s->gb, s->last_superframe, s->last_superframe_len * 8 + bit_offset); /* skip unused bits */ if (s->last_bitoffset > 0) skip_bits(&s->gb, s->last_bitoffset); @@ -866,11 +879,14 @@ static int wma_decode_superframe(AVCodecContext *avctx, if (wma_decode_frame(s, samples) < 0) goto fail; samples += s->nb_channels * s->frame_len; + nb_frames--; } /* read each frame starting from bit_offset */ pos = bit_offset + 4 + 4 + s->byte_offset_bits + 3; - init_get_bits(&s->gb, buf + (pos >> 3), (MAX_CODED_SUPERFRAME_SIZE - (pos >> 3))*8); + if (pos >= MAX_CODED_SUPERFRAME_SIZE * 8 || pos > buf_size * 8) + return AVERROR_INVALIDDATA; + init_get_bits(&s->gb, buf + (pos >> 3), (buf_size - (pos >> 3))*8); len = pos & 7; if (len > 0) skip_bits(&s->gb, len); @@ -894,10 +910,6 @@ static int wma_decode_superframe(AVCodecContext *avctx, s->last_superframe_len = len; memcpy(s->last_superframe, buf + pos, len); } else { - if(s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ - av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); - goto fail; - } /* single frame decode */ if (wma_decode_frame(s, samples) < 0) goto fail; @@ -906,7 +918,9 @@ static int wma_decode_superframe(AVCodecContext *avctx, //av_log(NULL, AV_LOG_ERROR, "%d %d %d %d outbytes:%d eaten:%d\n", s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, (int8_t *)samples - (int8_t *)data, s->block_align); - *data_size = (int8_t *)samples - (int8_t *)data; + *got_frame_ptr = 1; + *(AVFrame *)data = s->frame; + return s->block_align; fail: /* when error, we reset the bit reservoir */ @@ -922,30 +936,28 @@ static av_cold void flush(AVCodecContext *avctx) s->last_superframe_len= 0; } -AVCodec ff_wmav1_decoder = -{ - "wmav1", - AVMEDIA_TYPE_AUDIO, - CODEC_ID_WMAV1, - sizeof(WMACodecContext), - wma_decode_init, - NULL, - ff_wma_end, - wma_decode_superframe, - .flush=flush, - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), +AVCodec ff_wmav1_decoder = { + .name = "wmav1", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_WMAV1, + .priv_data_size = sizeof(WMACodecContext), + .init = wma_decode_init, + .close = ff_wma_end, + .decode = wma_decode_superframe, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), }; -AVCodec ff_wmav2_decoder = -{ - "wmav2", - AVMEDIA_TYPE_AUDIO, - CODEC_ID_WMAV2, - sizeof(WMACodecContext), - wma_decode_init, - NULL, - ff_wma_end, - wma_decode_superframe, - .flush=flush, - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), +AVCodec ff_wmav2_decoder = { + .name = "wmav2", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_WMAV2, + .priv_data_size = sizeof(WMACodecContext), + .init = wma_decode_init, + .close = ff_wma_end, + .decode = wma_decode_superframe, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), };