From abd8b9e7e05be481163624a9b0b1a572757e5633 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 16 Oct 2012 14:07:04 -0400 Subject: [PATCH] libmp3lame: resize the output buffer if needed The LAME API documentation for the required buffer size refers to the size for a single encode call. However, we store multiple frames in the same output buffer but only read 1 frame at a time out of it. As a result, the buffer size given in lame_encode_buffer() is actually smaller than what it should be. Since we do not know how many frames it will end up buffering, it is best to just reallocate if needed. --- libavcodec/libmp3lame.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 871156ff02..947edc0503 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -44,8 +44,9 @@ typedef struct LAMEContext { AVClass *class; AVCodecContext *avctx; lame_global_flags *gfp; - uint8_t buffer[BUFFER_SIZE]; + uint8_t *buffer; int buffer_index; + int buffer_size; int reservoir; float *samples_flt[2]; AudioFrameQueue afq; @@ -53,6 +54,26 @@ typedef struct LAMEContext { } LAMEContext; +static int realloc_buffer(LAMEContext *s) +{ + if (!s->buffer || s->buffer_size - s->buffer_index < BUFFER_SIZE) { + uint8_t *tmp; + int new_size = s->buffer_index + 2 * BUFFER_SIZE; + + av_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size, + new_size); + tmp = av_realloc(s->buffer, new_size); + if (!tmp) { + av_freep(&s->buffer); + s->buffer_size = s->buffer_index = 0; + return AVERROR(ENOMEM); + } + s->buffer = tmp; + s->buffer_size = new_size; + } + return 0; +} + static av_cold int mp3lame_encode_close(AVCodecContext *avctx) { LAMEContext *s = avctx->priv_data; @@ -62,6 +83,7 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx) #endif av_freep(&s->samples_flt[0]); av_freep(&s->samples_flt[1]); + av_freep(&s->buffer); ff_af_queue_close(&s->afq); @@ -141,6 +163,10 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) } } + ret = realloc_buffer(s); + if (ret < 0) + goto error; + ff_dsputil_init(&s->dsp, avctx); return 0; @@ -154,7 +180,7 @@ error: (const buf_type *)buf_name[0], \ (const buf_type *)buf_name[1], frame->nb_samples, \ s->buffer + s->buffer_index, \ - BUFFER_SIZE - s->buffer_index); \ + s->buffer_size - s->buffer_index); \ } while (0) static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, @@ -197,11 +223,16 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (lame_result == -1) { av_log(avctx, AV_LOG_ERROR, "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", - s->buffer_index, BUFFER_SIZE - s->buffer_index); + s->buffer_index, s->buffer_size - s->buffer_index); } return -1; } s->buffer_index += lame_result; + ret = realloc_buffer(s); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "error reallocating output buffer\n"); + return ret; + } /* add current frame to the queue */ if (frame) {