annotate ffmpeg/libavcodec/libfaac.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Interface to libfaac for aac encoding
yading@10 3 * Copyright (c) 2002 Gildas Bazin <gbazin@netcourrier.com>
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Interface to libfaac for aac encoding.
yading@10 25 */
yading@10 26
yading@10 27 #include <faac.h>
yading@10 28
yading@10 29 #include "libavutil/channel_layout.h"
yading@10 30 #include "libavutil/common.h"
yading@10 31 #include "avcodec.h"
yading@10 32 #include "audio_frame_queue.h"
yading@10 33 #include "internal.h"
yading@10 34
yading@10 35
yading@10 36 /* libfaac has an encoder delay of 1024 samples */
yading@10 37 #define FAAC_DELAY_SAMPLES 1024
yading@10 38
yading@10 39 typedef struct FaacAudioContext {
yading@10 40 faacEncHandle faac_handle;
yading@10 41 AudioFrameQueue afq;
yading@10 42 } FaacAudioContext;
yading@10 43
yading@10 44 static av_cold int Faac_encode_close(AVCodecContext *avctx)
yading@10 45 {
yading@10 46 FaacAudioContext *s = avctx->priv_data;
yading@10 47
yading@10 48 av_freep(&avctx->extradata);
yading@10 49 ff_af_queue_close(&s->afq);
yading@10 50
yading@10 51 if (s->faac_handle)
yading@10 52 faacEncClose(s->faac_handle);
yading@10 53
yading@10 54 return 0;
yading@10 55 }
yading@10 56
yading@10 57 static const int channel_maps[][6] = {
yading@10 58 { 2, 0, 1 }, //< C L R
yading@10 59 { 2, 0, 1, 3 }, //< C L R Cs
yading@10 60 { 2, 0, 1, 3, 4 }, //< C L R Ls Rs
yading@10 61 { 2, 0, 1, 4, 5, 3 }, //< C L R Ls Rs LFE
yading@10 62 };
yading@10 63
yading@10 64 static av_cold int Faac_encode_init(AVCodecContext *avctx)
yading@10 65 {
yading@10 66 FaacAudioContext *s = avctx->priv_data;
yading@10 67 faacEncConfigurationPtr faac_cfg;
yading@10 68 unsigned long samples_input, max_bytes_output;
yading@10 69 int ret;
yading@10 70
yading@10 71 /* number of channels */
yading@10 72 if (avctx->channels < 1 || avctx->channels > 6) {
yading@10 73 av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels);
yading@10 74 ret = AVERROR(EINVAL);
yading@10 75 goto error;
yading@10 76 }
yading@10 77
yading@10 78 s->faac_handle = faacEncOpen(avctx->sample_rate,
yading@10 79 avctx->channels,
yading@10 80 &samples_input, &max_bytes_output);
yading@10 81 if (!s->faac_handle) {
yading@10 82 av_log(avctx, AV_LOG_ERROR, "error in faacEncOpen()\n");
yading@10 83 ret = AVERROR_UNKNOWN;
yading@10 84 goto error;
yading@10 85 }
yading@10 86
yading@10 87 /* check faac version */
yading@10 88 faac_cfg = faacEncGetCurrentConfiguration(s->faac_handle);
yading@10 89 if (faac_cfg->version != FAAC_CFG_VERSION) {
yading@10 90 av_log(avctx, AV_LOG_ERROR, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION, faac_cfg->version);
yading@10 91 ret = AVERROR(EINVAL);
yading@10 92 goto error;
yading@10 93 }
yading@10 94
yading@10 95 /* put the options in the configuration struct */
yading@10 96 switch(avctx->profile) {
yading@10 97 case FF_PROFILE_AAC_MAIN:
yading@10 98 faac_cfg->aacObjectType = MAIN;
yading@10 99 break;
yading@10 100 case FF_PROFILE_UNKNOWN:
yading@10 101 case FF_PROFILE_AAC_LOW:
yading@10 102 faac_cfg->aacObjectType = LOW;
yading@10 103 break;
yading@10 104 case FF_PROFILE_AAC_SSR:
yading@10 105 faac_cfg->aacObjectType = SSR;
yading@10 106 break;
yading@10 107 case FF_PROFILE_AAC_LTP:
yading@10 108 faac_cfg->aacObjectType = LTP;
yading@10 109 break;
yading@10 110 default:
yading@10 111 av_log(avctx, AV_LOG_ERROR, "invalid AAC profile\n");
yading@10 112 ret = AVERROR(EINVAL);
yading@10 113 goto error;
yading@10 114 }
yading@10 115 faac_cfg->mpegVersion = MPEG4;
yading@10 116 faac_cfg->useTns = 0;
yading@10 117 faac_cfg->allowMidside = 1;
yading@10 118 faac_cfg->bitRate = avctx->bit_rate / avctx->channels;
yading@10 119 faac_cfg->bandWidth = avctx->cutoff;
yading@10 120 if(avctx->flags & CODEC_FLAG_QSCALE) {
yading@10 121 faac_cfg->bitRate = 0;
yading@10 122 faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA;
yading@10 123 }
yading@10 124 faac_cfg->outputFormat = 1;
yading@10 125 faac_cfg->inputFormat = FAAC_INPUT_16BIT;
yading@10 126 if (avctx->channels > 2)
yading@10 127 memcpy(faac_cfg->channel_map, channel_maps[avctx->channels-3],
yading@10 128 avctx->channels * sizeof(int));
yading@10 129
yading@10 130 avctx->frame_size = samples_input / avctx->channels;
yading@10 131
yading@10 132 /* Set decoder specific info */
yading@10 133 avctx->extradata_size = 0;
yading@10 134 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
yading@10 135
yading@10 136 unsigned char *buffer = NULL;
yading@10 137 unsigned long decoder_specific_info_size;
yading@10 138
yading@10 139 if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer,
yading@10 140 &decoder_specific_info_size)) {
yading@10 141 avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE);
yading@10 142 if (!avctx->extradata) {
yading@10 143 ret = AVERROR(ENOMEM);
yading@10 144 goto error;
yading@10 145 }
yading@10 146 avctx->extradata_size = decoder_specific_info_size;
yading@10 147 memcpy(avctx->extradata, buffer, avctx->extradata_size);
yading@10 148 faac_cfg->outputFormat = 0;
yading@10 149 }
yading@10 150 free(buffer);
yading@10 151 }
yading@10 152
yading@10 153 if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) {
yading@10 154 av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n");
yading@10 155 ret = AVERROR(EINVAL);
yading@10 156 goto error;
yading@10 157 }
yading@10 158
yading@10 159 avctx->delay = FAAC_DELAY_SAMPLES;
yading@10 160 ff_af_queue_init(avctx, &s->afq);
yading@10 161
yading@10 162 return 0;
yading@10 163 error:
yading@10 164 Faac_encode_close(avctx);
yading@10 165 return ret;
yading@10 166 }
yading@10 167
yading@10 168 static int Faac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
yading@10 169 const AVFrame *frame, int *got_packet_ptr)
yading@10 170 {
yading@10 171 FaacAudioContext *s = avctx->priv_data;
yading@10 172 int bytes_written, ret;
yading@10 173 int num_samples = frame ? frame->nb_samples : 0;
yading@10 174 void *samples = frame ? frame->data[0] : NULL;
yading@10 175
yading@10 176 if ((ret = ff_alloc_packet2(avctx, avpkt, (7 + 768) * avctx->channels)) < 0)
yading@10 177 return ret;
yading@10 178
yading@10 179 bytes_written = faacEncEncode(s->faac_handle, samples,
yading@10 180 num_samples * avctx->channels,
yading@10 181 avpkt->data, avpkt->size);
yading@10 182 if (bytes_written < 0) {
yading@10 183 av_log(avctx, AV_LOG_ERROR, "faacEncEncode() error\n");
yading@10 184 return bytes_written;
yading@10 185 }
yading@10 186
yading@10 187 /* add current frame to the queue */
yading@10 188 if (frame) {
yading@10 189 if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
yading@10 190 return ret;
yading@10 191 }
yading@10 192
yading@10 193 if (!bytes_written)
yading@10 194 return 0;
yading@10 195
yading@10 196 /* Get the next frame pts/duration */
yading@10 197 ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
yading@10 198 &avpkt->duration);
yading@10 199
yading@10 200 avpkt->size = bytes_written;
yading@10 201 *got_packet_ptr = 1;
yading@10 202 return 0;
yading@10 203 }
yading@10 204
yading@10 205 static const AVProfile profiles[] = {
yading@10 206 { FF_PROFILE_AAC_MAIN, "Main" },
yading@10 207 { FF_PROFILE_AAC_LOW, "LC" },
yading@10 208 { FF_PROFILE_AAC_SSR, "SSR" },
yading@10 209 { FF_PROFILE_AAC_LTP, "LTP" },
yading@10 210 { FF_PROFILE_UNKNOWN },
yading@10 211 };
yading@10 212
yading@10 213 static const uint64_t faac_channel_layouts[] = {
yading@10 214 AV_CH_LAYOUT_MONO,
yading@10 215 AV_CH_LAYOUT_STEREO,
yading@10 216 AV_CH_LAYOUT_SURROUND,
yading@10 217 AV_CH_LAYOUT_4POINT0,
yading@10 218 AV_CH_LAYOUT_5POINT0_BACK,
yading@10 219 AV_CH_LAYOUT_5POINT1_BACK,
yading@10 220 0
yading@10 221 };
yading@10 222
yading@10 223 AVCodec ff_libfaac_encoder = {
yading@10 224 .name = "libfaac",
yading@10 225 .type = AVMEDIA_TYPE_AUDIO,
yading@10 226 .id = AV_CODEC_ID_AAC,
yading@10 227 .priv_data_size = sizeof(FaacAudioContext),
yading@10 228 .init = Faac_encode_init,
yading@10 229 .encode2 = Faac_encode_frame,
yading@10 230 .close = Faac_encode_close,
yading@10 231 .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
yading@10 232 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
yading@10 233 AV_SAMPLE_FMT_NONE },
yading@10 234 .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Coding)"),
yading@10 235 .profiles = NULL_IF_CONFIG_SMALL(profiles),
yading@10 236 .channel_layouts = faac_channel_layouts,
yading@10 237 };