Merge commit 'e57c4706e969afa1f2384481b955ccd9494cddb5'

* commit 'e57c4706e969afa1f2384481b955ccd9494cddb5':
  lavc: don't reuse audio buffers

This commit causes a 0.5% speedloss for mp3 and 2% for raw pcm, that is
"time ffmpeg" style tested thus includes disk IO, demux and parsing

I would not have merged it if it wasnt required for the "new" buffer API
but sadly it is.
Once the new API is in ill reimplement proper buffer reuse, which will
fix this speedloss. In case we choose not to merge the "new" buffer
API then this commit here should be reverted.

Conflicts:
	libavcodec/internal.h
	libavcodec/utils.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-12-05 16:25:03 +01:00
commit 83db6cb521
2 changed files with 17 additions and 68 deletions

View File

@ -39,9 +39,6 @@ typedef struct InternalBuffer {
int width;
int height;
enum AVPixelFormat pix_fmt;
uint8_t **extended_data;
int audio_data_size;
int nb_channels;
} InternalBuffer;
typedef struct AVCodecInternal {
@ -79,6 +76,12 @@ typedef struct AVCodecInternal {
*/
int last_audio_frame;
/**
* The data for the last allocated audio frame.
* Stored here so we can free it.
*/
uint8_t *audio_data;
/**
* temporary buffer used for encoders to store their bitstream
*/

View File

@ -342,72 +342,29 @@ int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal;
InternalBuffer *buf;
int buf_size, ret;
av_freep(&avci->audio_data);
buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
frame->nb_samples, avctx->sample_fmt,
0);
if (buf_size < 0)
return AVERROR(EINVAL);
/* allocate InternalBuffer if needed */
if (!avci->buffer) {
avci->buffer = av_mallocz(sizeof(InternalBuffer));
if (!avci->buffer)
return AVERROR(ENOMEM);
}
buf = avci->buffer;
frame->data[0] = av_mallocz(buf_size);
if (!frame->data[0])
return AVERROR(ENOMEM);
/* if there is a previously-used internal buffer, check its size and
* channel count to see if we can reuse it */
if (buf->extended_data) {
/* if current buffer is too small, free it */
if (buf->extended_data[0] && buf_size > buf->audio_data_size) {
av_free(buf->extended_data[0]);
if (buf->extended_data != buf->data)
av_free(buf->extended_data);
buf->extended_data = NULL;
buf->data[0] = NULL;
}
/* if number of channels has changed, reset and/or free extended data
* pointers but leave data buffer in buf->data[0] for reuse */
if (buf->nb_channels != avctx->channels) {
if (buf->extended_data != buf->data)
av_free(buf->extended_data);
buf->extended_data = NULL;
}
}
/* if there is no previous buffer or the previous buffer cannot be used
* as-is, allocate a new buffer and/or rearrange the channel pointers */
if (!buf->extended_data) {
if (!buf->data[0]) {
if (!(buf->data[0] = av_mallocz(buf_size)))
return AVERROR(ENOMEM);
buf->audio_data_size = buf_size;
}
if ((ret = avcodec_fill_audio_frame(frame, avctx->channels,
avctx->sample_fmt, buf->data[0],
buf->audio_data_size, 0)) < 0)
return ret;
if (frame->extended_data == frame->data)
buf->extended_data = buf->data;
else
buf->extended_data = frame->extended_data;
memcpy(buf->data, frame->data, sizeof(frame->data));
buf->linesize[0] = frame->linesize[0];
buf->nb_channels = avctx->channels;
} else {
/* copy InternalBuffer info to the AVFrame */
frame->extended_data = buf->extended_data;
frame->linesize[0] = buf->linesize[0];
memcpy(frame->data, buf->data, sizeof(frame->data));
ret = avcodec_fill_audio_frame(frame, avctx->channels, avctx->sample_fmt,
frame->data[0], buf_size, 0);
if (ret < 0) {
av_freep(&frame->data[0]);
return ret;
}
frame->type = FF_BUFFER_TYPE_INTERNAL;
avci->audio_data = frame->data[0];
if (avctx->debug & FF_DEBUG_BUFFERS)
av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p, "
"internal audio buffer used\n", frame);
@ -2270,18 +2227,7 @@ static void video_free_buffers(AVCodecContext *s)
static void audio_free_buffers(AVCodecContext *avctx)
{
AVCodecInternal *avci = avctx->internal;
InternalBuffer *buf;
if (!avci->buffer)
return;
buf = avci->buffer;
if (buf->extended_data) {
av_free(buf->extended_data[0]);
if (buf->extended_data != buf->data)
av_freep(&buf->extended_data);
}
av_freep(&avci->buffer);
av_freep(&avci->audio_data);
}
void avcodec_default_free_buffers(AVCodecContext *avctx)