Libav
|
00001 /* 00002 * Interface to libfaac for aac encoding 00003 * Copyright (c) 2002 Gildas Bazin <gbazin@netcourrier.com> 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "avcodec.h" 00028 #include <faac.h> 00029 00030 typedef struct FaacAudioContext { 00031 faacEncHandle faac_handle; 00032 } FaacAudioContext; 00033 00034 static av_cold int Faac_encode_init(AVCodecContext *avctx) 00035 { 00036 FaacAudioContext *s = avctx->priv_data; 00037 faacEncConfigurationPtr faac_cfg; 00038 unsigned long samples_input, max_bytes_output; 00039 00040 /* number of channels */ 00041 if (avctx->channels < 1 || avctx->channels > 6) { 00042 av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels); 00043 return -1; 00044 } 00045 00046 s->faac_handle = faacEncOpen(avctx->sample_rate, 00047 avctx->channels, 00048 &samples_input, &max_bytes_output); 00049 00050 /* check faac version */ 00051 faac_cfg = faacEncGetCurrentConfiguration(s->faac_handle); 00052 if (faac_cfg->version != FAAC_CFG_VERSION) { 00053 av_log(avctx, AV_LOG_ERROR, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION, faac_cfg->version); 00054 faacEncClose(s->faac_handle); 00055 return -1; 00056 } 00057 00058 /* put the options in the configuration struct */ 00059 switch(avctx->profile) { 00060 case FF_PROFILE_AAC_MAIN: 00061 faac_cfg->aacObjectType = MAIN; 00062 break; 00063 case FF_PROFILE_UNKNOWN: 00064 case FF_PROFILE_AAC_LOW: 00065 faac_cfg->aacObjectType = LOW; 00066 break; 00067 case FF_PROFILE_AAC_SSR: 00068 faac_cfg->aacObjectType = SSR; 00069 break; 00070 case FF_PROFILE_AAC_LTP: 00071 faac_cfg->aacObjectType = LTP; 00072 break; 00073 default: 00074 av_log(avctx, AV_LOG_ERROR, "invalid AAC profile\n"); 00075 faacEncClose(s->faac_handle); 00076 return -1; 00077 } 00078 faac_cfg->mpegVersion = MPEG4; 00079 faac_cfg->useTns = 0; 00080 faac_cfg->allowMidside = 1; 00081 faac_cfg->bitRate = avctx->bit_rate / avctx->channels; 00082 faac_cfg->bandWidth = avctx->cutoff; 00083 if(avctx->flags & CODEC_FLAG_QSCALE) { 00084 faac_cfg->bitRate = 0; 00085 faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA; 00086 } 00087 faac_cfg->outputFormat = 1; 00088 faac_cfg->inputFormat = FAAC_INPUT_16BIT; 00089 00090 avctx->frame_size = samples_input / avctx->channels; 00091 00092 avctx->coded_frame= avcodec_alloc_frame(); 00093 avctx->coded_frame->key_frame= 1; 00094 00095 /* Set decoder specific info */ 00096 avctx->extradata_size = 0; 00097 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { 00098 00099 unsigned char *buffer = NULL; 00100 unsigned long decoder_specific_info_size; 00101 00102 if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer, 00103 &decoder_specific_info_size)) { 00104 avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); 00105 avctx->extradata_size = decoder_specific_info_size; 00106 memcpy(avctx->extradata, buffer, avctx->extradata_size); 00107 faac_cfg->outputFormat = 0; 00108 } 00109 #undef free 00110 free(buffer); 00111 #define free please_use_av_free 00112 } 00113 00114 if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) { 00115 av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n"); 00116 return -1; 00117 } 00118 00119 return 0; 00120 } 00121 00122 static int Faac_encode_frame(AVCodecContext *avctx, 00123 unsigned char *frame, int buf_size, void *data) 00124 { 00125 FaacAudioContext *s = avctx->priv_data; 00126 int bytes_written; 00127 00128 bytes_written = faacEncEncode(s->faac_handle, 00129 data, 00130 avctx->frame_size * avctx->channels, 00131 frame, 00132 buf_size); 00133 00134 return bytes_written; 00135 } 00136 00137 static av_cold int Faac_encode_close(AVCodecContext *avctx) 00138 { 00139 FaacAudioContext *s = avctx->priv_data; 00140 00141 av_freep(&avctx->coded_frame); 00142 av_freep(&avctx->extradata); 00143 00144 faacEncClose(s->faac_handle); 00145 return 0; 00146 } 00147 00148 AVCodec libfaac_encoder = { 00149 "libfaac", 00150 AVMEDIA_TYPE_AUDIO, 00151 CODEC_ID_AAC, 00152 sizeof(FaacAudioContext), 00153 Faac_encode_init, 00154 Faac_encode_frame, 00155 Faac_encode_close, 00156 .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, 00157 .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"), 00158 };