From 473b297f26b51a5d6bf4cd0126d950cc4b105bd7 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 22 Aug 2012 12:23:21 -0400 Subject: libmp3lame: use planar sample formats --- libavcodec/libmp3lame.c | 104 ++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 66 deletions(-) (limited to 'libavcodec/libmp3lame.c') diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 7a76d1fe37..871156ff02 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -33,6 +33,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" +#include "dsputil.h" #include "internal.h" #include "mpegaudio.h" #include "mpegaudiodecheader.h" @@ -46,8 +47,9 @@ typedef struct LAMEContext { uint8_t buffer[BUFFER_SIZE]; int buffer_index; int reservoir; - void *planar_samples[2]; + float *samples_flt[2]; AudioFrameQueue afq; + DSPContext dsp; } LAMEContext; @@ -58,8 +60,8 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx) #if FF_API_OLD_ENCODE_AUDIO av_freep(&avctx->coded_frame); #endif - av_freep(&s->planar_samples[0]); - av_freep(&s->planar_samples[1]); + av_freep(&s->samples_flt[0]); + av_freep(&s->samples_flt[1]); ff_af_queue_close(&s->afq); @@ -126,93 +128,63 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) } #endif - /* sample format */ - if (avctx->sample_fmt == AV_SAMPLE_FMT_S32 || - avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { + /* allocate float sample buffers */ + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) { int ch; for (ch = 0; ch < avctx->channels; ch++) { - s->planar_samples[ch] = av_malloc(avctx->frame_size * - av_get_bytes_per_sample(avctx->sample_fmt)); - if (!s->planar_samples[ch]) { + s->samples_flt[ch] = av_malloc(avctx->frame_size * + sizeof(*s->samples_flt[ch])); + if (!s->samples_flt[ch]) { ret = AVERROR(ENOMEM); goto error; } } } + ff_dsputil_init(&s->dsp, avctx); + return 0; error: mp3lame_encode_close(avctx); return ret; } -#define DEINTERLEAVE(type, scale) do { \ - int ch, i; \ - for (ch = 0; ch < s->avctx->channels; ch++) { \ - const type *input = samples; \ - type *output = s->planar_samples[ch]; \ - input += ch; \ - for (i = 0; i < nb_samples; i++) { \ - output[i] = *input * scale; \ - input += s->avctx->channels; \ - } \ - } \ +#define ENCODE_BUFFER(func, buf_type, buf_name) do { \ + lame_result = func(s->gfp, \ + (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); \ } while (0) -static int encode_frame_int16(LAMEContext *s, void *samples, int nb_samples) -{ - if (s->avctx->channels > 1) { - return lame_encode_buffer_interleaved(s->gfp, samples, - nb_samples, - s->buffer + s->buffer_index, - BUFFER_SIZE - s->buffer_index); - } else { - return lame_encode_buffer(s->gfp, samples, NULL, nb_samples, - s->buffer + s->buffer_index, - BUFFER_SIZE - s->buffer_index); - } -} - -static int encode_frame_int32(LAMEContext *s, void *samples, int nb_samples) -{ - DEINTERLEAVE(int32_t, 1); - - return lame_encode_buffer_int(s->gfp, - s->planar_samples[0], s->planar_samples[1], - nb_samples, - s->buffer + s->buffer_index, - BUFFER_SIZE - s->buffer_index); -} - -static int encode_frame_float(LAMEContext *s, void *samples, int nb_samples) -{ - DEINTERLEAVE(float, 32768.0f); - - return lame_encode_buffer_float(s->gfp, - s->planar_samples[0], s->planar_samples[1], - nb_samples, - s->buffer + s->buffer_index, - BUFFER_SIZE - s->buffer_index); -} - static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { LAMEContext *s = avctx->priv_data; MPADecodeHeader hdr; - int len, ret; + int len, ret, ch; int lame_result; if (frame) { switch (avctx->sample_fmt) { - case AV_SAMPLE_FMT_S16: - lame_result = encode_frame_int16(s, frame->data[0], frame->nb_samples); + case AV_SAMPLE_FMT_S16P: + ENCODE_BUFFER(lame_encode_buffer, int16_t, frame->data); break; - case AV_SAMPLE_FMT_S32: - lame_result = encode_frame_int32(s, frame->data[0], frame->nb_samples); + case AV_SAMPLE_FMT_S32P: + ENCODE_BUFFER(lame_encode_buffer_int, int32_t, frame->data); break; - case AV_SAMPLE_FMT_FLT: - lame_result = encode_frame_float(s, frame->data[0], frame->nb_samples); + case AV_SAMPLE_FMT_FLTP: + if (frame->linesize[0] < 4 * FFALIGN(frame->nb_samples, 8)) { + av_log(avctx, AV_LOG_ERROR, "inadequate AVFrame plane padding\n"); + return AVERROR(EINVAL); + } + for (ch = 0; ch < avctx->channels; ch++) { + s->dsp.vector_fmul_scalar(s->samples_flt[ch], + (const float *)frame->data[ch], + 32768.0f, + FFALIGN(frame->nb_samples, 8)); + } + ENCODE_BUFFER(lame_encode_buffer_float, float, s->samples_flt); break; default: return AVERROR_BUG; @@ -300,9 +272,9 @@ AVCodec ff_libmp3lame_encoder = { .encode2 = mp3lame_encode_frame, .close = mp3lame_encode_close, .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_S16, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .supported_samplerates = libmp3lame_sample_rates, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, -- cgit v1.2.3