1/* 2 * Interface to libfaac for aac encoding 3 * Copyright (c) 2002 Gildas Bazin <gbazin@netcourrier.com> 4 * 5 * This file is part of Libav. 6 * 7 * Libav is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * Libav is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Interface to libfaac for aac encoding. 25 */ 26 27#include "avcodec.h" 28#include <faac.h> 29 30typedef struct FaacAudioContext { 31 faacEncHandle faac_handle; 32} FaacAudioContext; 33 34static av_cold int Faac_encode_init(AVCodecContext *avctx) 35{ 36 FaacAudioContext *s = avctx->priv_data; 37 faacEncConfigurationPtr faac_cfg; 38 unsigned long samples_input, max_bytes_output; 39 40 /* number of channels */ 41 if (avctx->channels < 1 || avctx->channels > 6) { 42 av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels); 43 return -1; 44 } 45 46 s->faac_handle = faacEncOpen(avctx->sample_rate, 47 avctx->channels, 48 &samples_input, &max_bytes_output); 49 50 /* check faac version */ 51 faac_cfg = faacEncGetCurrentConfiguration(s->faac_handle); 52 if (faac_cfg->version != FAAC_CFG_VERSION) { 53 av_log(avctx, AV_LOG_ERROR, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION, faac_cfg->version); 54 faacEncClose(s->faac_handle); 55 return -1; 56 } 57 58 /* put the options in the configuration struct */ 59 switch(avctx->profile) { 60 case FF_PROFILE_AAC_MAIN: 61 faac_cfg->aacObjectType = MAIN; 62 break; 63 case FF_PROFILE_UNKNOWN: 64 case FF_PROFILE_AAC_LOW: 65 faac_cfg->aacObjectType = LOW; 66 break; 67 case FF_PROFILE_AAC_SSR: 68 faac_cfg->aacObjectType = SSR; 69 break; 70 case FF_PROFILE_AAC_LTP: 71 faac_cfg->aacObjectType = LTP; 72 break; 73 default: 74 av_log(avctx, AV_LOG_ERROR, "invalid AAC profile\n"); 75 faacEncClose(s->faac_handle); 76 return -1; 77 } 78 faac_cfg->mpegVersion = MPEG4; 79 faac_cfg->useTns = 0; 80 faac_cfg->allowMidside = 1; 81 faac_cfg->bitRate = avctx->bit_rate / avctx->channels; 82 faac_cfg->bandWidth = avctx->cutoff; 83 if(avctx->flags & CODEC_FLAG_QSCALE) { 84 faac_cfg->bitRate = 0; 85 faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA; 86 } 87 faac_cfg->outputFormat = 1; 88 faac_cfg->inputFormat = FAAC_INPUT_16BIT; 89 90 avctx->frame_size = samples_input / avctx->channels; 91 92 avctx->coded_frame= avcodec_alloc_frame(); 93 avctx->coded_frame->key_frame= 1; 94 95 /* Set decoder specific info */ 96 avctx->extradata_size = 0; 97 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { 98 99 unsigned char *buffer = NULL; 100 unsigned long decoder_specific_info_size; 101 102 if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer, 103 &decoder_specific_info_size)) { 104 avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); 105 avctx->extradata_size = decoder_specific_info_size; 106 memcpy(avctx->extradata, buffer, avctx->extradata_size); 107 faac_cfg->outputFormat = 0; 108 } 109#undef free 110 free(buffer); 111#define free please_use_av_free 112 } 113 114 if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) { 115 av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n"); 116 return -1; 117 } 118 119 return 0; 120} 121 122static int Faac_encode_frame(AVCodecContext *avctx, 123 unsigned char *frame, int buf_size, void *data) 124{ 125 FaacAudioContext *s = avctx->priv_data; 126 int bytes_written; 127 int num_samples = data ? avctx->frame_size : 0; 128 129 bytes_written = faacEncEncode(s->faac_handle, 130 data, 131 num_samples * avctx->channels, 132 frame, 133 buf_size); 134 135 return bytes_written; 136} 137 138static av_cold int Faac_encode_close(AVCodecContext *avctx) 139{ 140 FaacAudioContext *s = avctx->priv_data; 141 142 av_freep(&avctx->coded_frame); 143 av_freep(&avctx->extradata); 144 145 faacEncClose(s->faac_handle); 146 return 0; 147} 148 149static const AVProfile profiles[] = { 150 { FF_PROFILE_AAC_MAIN, "Main" }, 151 { FF_PROFILE_AAC_LOW, "LC" }, 152 { FF_PROFILE_AAC_SSR, "SSR" }, 153 { FF_PROFILE_AAC_LTP, "LTP" }, 154 { FF_PROFILE_UNKNOWN }, 155}; 156 157AVCodec ff_libfaac_encoder = { 158 .name = "libfaac", 159 .type = AVMEDIA_TYPE_AUDIO, 160 .id = CODEC_ID_AAC, 161 .priv_data_size = sizeof(FaacAudioContext), 162 .init = Faac_encode_init, 163 .encode = Faac_encode_frame, 164 .close = Faac_encode_close, 165 .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, 166 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, 167 .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"), 168 .profiles = NULL_IF_CONFIG_SMALL(profiles), 169}; 170