Merge commit '3c650efb81aaa3b395ba4606ee68a47ee4efb57b'
[ffmpeg.git] / libavcodec / libaacplus.c
index a5ededb..545e240 100644 (file)
  * Interface to libaacplus for aac+ (sbr+ps) encoding.
  */
 
-#include "avcodec.h"
 #include <aacplus.h>
 
+#include "avcodec.h"
+#include "internal.h"
+
 typedef struct aacPlusAudioContext {
     aacplusEncHandle aacplus_handle;
+    unsigned long max_output_bytes;
+    unsigned long samples_input;
 } aacPlusAudioContext;
 
 static av_cold int aacPlus_encode_init(AVCodecContext *avctx)
 {
     aacPlusAudioContext *s = avctx->priv_data;
     aacplusEncConfiguration *aacplus_cfg;
-    unsigned long samples_input, max_bytes_output;
 
     /* number of channels */
     if (avctx->channels < 1 || avctx->channels > 2) {
         av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels);
-        return -1;
+        return AVERROR(EINVAL);
     }
 
-    s->aacplus_handle = aacplusEncOpen(avctx->sample_rate,
-                                 avctx->channels,
-                                 &samples_input, &max_bytes_output);
-    if(!s->aacplus_handle) {
-            av_log(avctx, AV_LOG_ERROR, "can't open encoder\n");
-            return -1;
+    if (avctx->profile != FF_PROFILE_AAC_LOW && avctx->profile != FF_PROFILE_UNKNOWN) {
+        av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC supported\n", avctx->profile);
+        return AVERROR(EINVAL);
+    }
+
+    s->aacplus_handle = aacplusEncOpen(avctx->sample_rate, avctx->channels,
+                                       &s->samples_input, &s->max_output_bytes);
+    if (!s->aacplus_handle) {
+        av_log(avctx, AV_LOG_ERROR, "can't open encoder\n");
+        return AVERROR(EINVAL);
     }
 
     /* check aacplus version */
     aacplus_cfg = aacplusEncGetCurrentConfiguration(s->aacplus_handle);
 
-    /* put the options in the configuration struct */
-    if(avctx->profile != FF_PROFILE_AAC_LOW && avctx->profile != FF_PROFILE_UNKNOWN) {
-            av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC supported\n", avctx->profile);
-            aacplusEncClose(s->aacplus_handle);
-            return -1;
-    }
-
     aacplus_cfg->bitRate = avctx->bit_rate;
     aacplus_cfg->bandWidth = avctx->cutoff;
     aacplus_cfg->outputFormat = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER);
-    aacplus_cfg->inputFormat = AACPLUS_INPUT_16BIT;
+    aacplus_cfg->inputFormat = avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? AACPLUS_INPUT_FLOAT : AACPLUS_INPUT_16BIT;
     if (!aacplusEncSetConfiguration(s->aacplus_handle, aacplus_cfg)) {
         av_log(avctx, AV_LOG_ERROR, "libaacplus doesn't support this output format!\n");
-        return -1;
+        return AVERROR(EINVAL);
     }
 
-    avctx->frame_size = samples_input / avctx->channels;
-
-    avctx->coded_frame= avcodec_alloc_frame();
-    avctx->coded_frame->key_frame= 1;
+    avctx->frame_size = s->samples_input / avctx->channels;
 
     /* Set decoder specific info */
     avctx->extradata_size = 0;
@@ -88,47 +85,57 @@ static av_cold int aacPlus_encode_init(AVCodecContext *avctx)
             avctx->extradata_size = decoder_specific_info_size;
             memcpy(avctx->extradata, buffer, avctx->extradata_size);
         }
-#undef free
         free(buffer);
-#define free please_use_av_free
     }
     return 0;
 }
 
-static int aacPlus_encode_frame(AVCodecContext *avctx,
-                             unsigned char *frame, int buf_size, void *data)
+static int aacPlus_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                                const AVFrame *frame, int *got_packet)
 {
     aacPlusAudioContext *s = avctx->priv_data;
-    int bytes_written;
+    int32_t *input_buffer = (int32_t *)frame->data[0];
+    int ret;
 
-    bytes_written = aacplusEncEncode(s->aacplus_handle,
-                                  data,
-                                  avctx->frame_size * avctx->channels,
-                                  frame,
-                                  buf_size);
+    if ((ret = ff_alloc_packet2(avctx, pkt, s->max_output_bytes)) < 0)
+        return ret;
 
-    return bytes_written;
+    pkt->size = aacplusEncEncode(s->aacplus_handle, input_buffer,
+                                 s->samples_input, pkt->data, pkt->size);
+    *got_packet   = 1;
+    pkt->pts      = frame->pts;
+    return 0;
 }
 
 static av_cold int aacPlus_encode_close(AVCodecContext *avctx)
 {
     aacPlusAudioContext *s = avctx->priv_data;
 
-    av_freep(&avctx->coded_frame);
     av_freep(&avctx->extradata);
-
     aacplusEncClose(s->aacplus_handle);
+
     return 0;
 }
 
+static const AVProfile profiles[] = {
+    { FF_PROFILE_AAC_LOW, "LC" },
+    { FF_PROFILE_UNKNOWN },
+};
+
 AVCodec ff_libaacplus_encoder = {
-    "libaacplus",
-    AVMEDIA_TYPE_AUDIO,
-    CODEC_ID_AAC,
-    sizeof(aacPlusAudioContext),
-    aacPlus_encode_init,
-    aacPlus_encode_frame,
-    aacPlus_encode_close,
-    .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
-    .long_name = NULL_IF_CONFIG_SMALL("libaacplus AAC+ (Advanced Audio Codec with SBR+PS)"),
+    .name           = "libaacplus",
+    .long_name      = NULL_IF_CONFIG_SMALL("libaacplus AAC+ (Advanced Audio Codec with SBR+PS)"),
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_AAC,
+    .priv_data_size = sizeof(aacPlusAudioContext),
+    .init           = aacPlus_encode_init,
+    .encode2        = aacPlus_encode_frame,
+    .close          = aacPlus_encode_close,
+    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+                                                     AV_SAMPLE_FMT_FLT,
+                                                     AV_SAMPLE_FMT_NONE },
+    .profiles       = profiles,
+    .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
+                                            AV_CH_LAYOUT_STEREO,
+                                            0 },
 };