1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

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.
This commit is contained in:
Justin Ruggles 2012-10-16 14:07:04 -04:00
parent c75848cd4c
commit abd8b9e7e0

View File

@ -44,8 +44,9 @@ typedef struct LAMEContext {
AVClass *class; AVClass *class;
AVCodecContext *avctx; AVCodecContext *avctx;
lame_global_flags *gfp; lame_global_flags *gfp;
uint8_t buffer[BUFFER_SIZE]; uint8_t *buffer;
int buffer_index; int buffer_index;
int buffer_size;
int reservoir; int reservoir;
float *samples_flt[2]; float *samples_flt[2];
AudioFrameQueue afq; AudioFrameQueue afq;
@ -53,6 +54,26 @@ typedef struct LAMEContext {
} 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) static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
{ {
LAMEContext *s = avctx->priv_data; LAMEContext *s = avctx->priv_data;
@ -62,6 +83,7 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
#endif #endif
av_freep(&s->samples_flt[0]); av_freep(&s->samples_flt[0]);
av_freep(&s->samples_flt[1]); av_freep(&s->samples_flt[1]);
av_freep(&s->buffer);
ff_af_queue_close(&s->afq); 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); ff_dsputil_init(&s->dsp, avctx);
return 0; return 0;
@ -154,7 +180,7 @@ error:
(const buf_type *)buf_name[0], \ (const buf_type *)buf_name[0], \
(const buf_type *)buf_name[1], frame->nb_samples, \ (const buf_type *)buf_name[1], frame->nb_samples, \
s->buffer + s->buffer_index, \ s->buffer + s->buffer_index, \
BUFFER_SIZE - s->buffer_index); \ s->buffer_size - s->buffer_index); \
} while (0) } while (0)
static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, 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) { if (lame_result == -1) {
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
"lame: output buffer too small (buffer index: %d, free bytes: %d)\n", "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; return -1;
} }
s->buffer_index += lame_result; 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 */ /* add current frame to the queue */
if (frame) { if (frame) {