]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/libmp3lame.c
aarch64: vp9dsp: Fix vertical alignment in the init file
[ffmpeg] / libavcodec / libmp3lame.c
index 8f254389320d0ae5853bbf4de5aa2aa44eea9ac5..e4d0e001032dd2a7b8ea3d854e57beceb77feab6 100644 (file)
@@ -26,7 +26,9 @@
 
 #include <lame/lame.h>
 
-#include "libavutil/audioconvert.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/common.h"
+#include "libavutil/float_dsp.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
@@ -42,23 +44,41 @@ 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;
-    void *planar_samples[2];
+    int joint_stereo;
+    int abr;
+    float *samples_flt[2];
     AudioFrameQueue afq;
+    AVFloatDSPContext fdsp;
 } LAMEContext;
 
 
+static int realloc_buffer(LAMEContext *s)
+{
+    if (!s->buffer || s->buffer_size - s->buffer_index < BUFFER_SIZE) {
+        int new_size = s->buffer_index + 2 * BUFFER_SIZE, err;
+
+        ff_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size,
+                new_size);
+        if ((err = av_reallocp(&s->buffer, new_size)) < 0) {
+            s->buffer_size = s->buffer_index = 0;
+            return err;
+        }
+        s->buffer_size = new_size;
+    }
+    return 0;
+}
+
 static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
 {
     LAMEContext *s = avctx->priv_data;
 
-#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]);
+    av_freep(&s->buffer);
 
     ff_af_queue_close(&s->afq);
 
@@ -74,11 +94,11 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
     s->avctx = avctx;
 
     /* initialize LAME and get defaults */
-    if ((s->gfp = lame_init()) == NULL)
+    if (!(s->gfp = lame_init()))
         return AVERROR(ENOMEM);
 
     lame_set_num_channels(s->gfp, avctx->channels);
-    lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO);
+    lame_set_mode(s->gfp, avctx->channels > 1 ? s->joint_stereo ? JOINT_STEREO : STEREO : MONO);
 
     /* sample rate */
     lame_set_in_samplerate (s->gfp, avctx->sample_rate);
@@ -91,12 +111,17 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
         lame_set_quality(s->gfp, avctx->compression_level);
 
     /* rate control */
-    if (avctx->flags & CODEC_FLAG_QSCALE) {
+    if (avctx->flags & AV_CODEC_FLAG_QSCALE) { // VBR
         lame_set_VBR(s->gfp, vbr_default);
         lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA);
     } else {
-        if (avctx->bit_rate)
-            lame_set_brate(s->gfp, avctx->bit_rate / 1000);
+        if (avctx->bit_rate) {
+            if (s->abr) {                   // ABR
+                lame_set_VBR(s->gfp, vbr_abr);
+                lame_set_VBR_mean_bitrate_kbps(s->gfp, avctx->bit_rate / 1000);
+            } else                          // CBR
+                lame_set_brate(s->gfp, avctx->bit_rate / 1000);
+        }
     }
 
     /* do not get a Xing VBR header frame from LAME */
@@ -112,127 +137,99 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
     }
 
     /* get encoder delay */
-    avctx->delay = lame_get_encoder_delay(s->gfp) + 528 + 1;
+    avctx->initial_padding = lame_get_encoder_delay(s->gfp) + 528 + 1;
     ff_af_queue_init(avctx, &s->afq);
 
     avctx->frame_size  = lame_get_framesize(s->gfp);
 
-#if FF_API_OLD_ENCODE_AUDIO
-    avctx->coded_frame = avcodec_alloc_frame();
-    if (!avctx->coded_frame) {
-        ret = AVERROR(ENOMEM);
-        goto error;
-    }
-#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;
             }
         }
     }
 
+    ret = realloc_buffer(s);
+    if (ret < 0)
+        goto error;
+
+    avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
+
     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,                         \
+                       s->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;
+    uint32_t h;
 
     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->fdsp.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;
         }
     } else {
         lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index,
-                                        BUFFER_SIZE - s->buffer_index);
+                                        s->buffer_size - s->buffer_index);
     }
     if (lame_result < 0) {
         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) {
-        if ((ret = ff_af_queue_add(&s->afq, frame) < 0))
+        if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
             return ret;
     }
 
@@ -241,12 +238,18 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
        determine the frame size. */
     if (s->buffer_index < 4)
         return 0;
-    if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) {
+    h = AV_RB32(s->buffer);
+
+    ret = avpriv_mpegaudio_decode_header(&hdr, h);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid mp3 header at start of buffer\n");
+        return AVERROR_BUG;
+    } else if (ret) {
         av_log(avctx, AV_LOG_ERROR, "free format output not supported\n");
         return -1;
     }
     len = hdr.frame_size;
-    av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len,
+    ff_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len,
             s->buffer_index);
     if (len <= s->buffer_index) {
         if ((ret = ff_alloc_packet(avpkt, len))) {
@@ -270,7 +273,9 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 #define OFFSET(x) offsetof(LAMEContext, x)
 #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
-    { "reservoir", "Use bit reservoir.", OFFSET(reservoir), AV_OPT_TYPE_INT, { 1 }, 0, 1, AE },
+    { "reservoir", "Use bit reservoir.", OFFSET(reservoir), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AE },
+    { "joint_stereo", "Use joint stereo.", OFFSET(joint_stereo), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AE },
+    { "abr", "Use ABR", OFFSET(abr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE },
     { NULL },
 };
 
@@ -292,21 +297,22 @@ static const int libmp3lame_sample_rates[] = {
 
 AVCodec ff_libmp3lame_encoder = {
     .name                  = "libmp3lame",
+    .long_name             = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"),
     .type                  = AVMEDIA_TYPE_AUDIO,
-    .id                    = CODEC_ID_MP3,
+    .id                    = AV_CODEC_ID_MP3,
     .priv_data_size        = sizeof(LAMEContext),
     .init                  = mp3lame_encode_init,
     .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,
+    .capabilities          = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .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,
-                                                  AV_CH_LAYOUT_STEREO },
-    .long_name             = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"),
+                                                  AV_CH_LAYOUT_STEREO,
+                                                  0 },
     .priv_class            = &libmp3lame_class,
     .defaults              = libmp3lame_defaults,
 };