From 7551a55948a3520f75fd249eea7585d71fe4a8c8 Mon Sep 17 00:00:00 2001 From: Sascha Sommer Date: Sat, 5 Sep 2009 10:07:55 +0000 Subject: [PATCH] reduce output buffer needs (fixes playback of some multichannel files) Originally committed as revision 19763 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/wmaprodec.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index cf8fa32619..cd21c171e5 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -194,11 +194,13 @@ typedef struct WMAProDecodeCtx { int frame_offset; ///< frame offset in the bit reservoir int subframe_offset; ///< subframe offset in the bit reservoir uint8_t packet_loss; ///< set in case of bitstream error + uint8_t output_buffer_full; ///< flag indicating that the output buffer is full /* frame decode state */ 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_start; ///< start samplebuffer pointer float* samples; ///< current samplebuffer pointer float* samples_end; ///< maximum samplebuffer pointer uint8_t drc_gain; ///< gain for the DRC tool @@ -1256,9 +1258,13 @@ static int decode_frame(WMAProDecodeCtx *s) /** check for potential output buffer overflow */ if (s->num_channels * s->samples_per_frame > s->samples_end - s->samples) { - av_log(s->avctx, AV_LOG_ERROR, - "not enough space for the output samples\n"); - s->packet_loss = 1; + /** return an error if no frame could be decoded at all */ + if (s->samples_start == s->samples) { + av_log(s->avctx, AV_LOG_ERROR, + "not enough space for the output samples\n"); + s->packet_loss = 1; + } else + s->output_buffer_full = 1; return 0; } @@ -1451,12 +1457,13 @@ static int decode_packet(AVCodecContext *avctx, int packet_sequence_number; s->samples = data; + s->samples_start = data; s->samples_end = (float*)((int8_t*)data + *data_size); - s->buf_bit_size = buf_size << 3; - - *data_size = 0; + if (!s->output_buffer_full) { + s->buf_bit_size = buf_size << 3; + /** sanity check for the buffer length */ if (buf_size < avctx->block_align) return 0; @@ -1498,8 +1505,15 @@ static int decode_packet(AVCodecContext *avctx, } s->packet_loss = 0; + + } else { + /** continue decoding */ + s->output_buffer_full = 0; + more_frames = decode_frame(s); + } + /** decode the rest of the packet */ - while (!s->packet_loss && more_frames && + while (!s->packet_loss && !s->output_buffer_full && more_frames && remaining_bits(s, gb) > s->log2_frame_size) { int frame_size = show_bits(gb, s->log2_frame_size); @@ -1517,7 +1531,8 @@ static int decode_packet(AVCodecContext *avctx, more_frames = 0; } - if (!s->packet_loss && remaining_bits(s, gb) > 0) { + if (!s->output_buffer_full && !s->packet_loss && + remaining_bits(s, gb) > 0) { /** save the rest of the data so that it can be decoded with the next packet */ save_bits(s, gb, remaining_bits(s, gb), 0); @@ -1525,7 +1540,7 @@ static int decode_packet(AVCodecContext *avctx, *data_size = (int8_t *)s->samples - (int8_t *)data; - return avctx->block_align; + return (s->output_buffer_full)?0: avctx->block_align; } /**