00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avcodec.h"
00028 #include <faac.h>
00029
00030 typedef struct FaacAudioContext {
00031 faacEncHandle faac_handle;
00032 } FaacAudioContext;
00033
00034 static const int channel_maps[][6] = {
00035 { 2, 0, 1 },
00036 { 2, 0, 1, 3 },
00037 { 2, 0, 1, 3, 4 },
00038 { 2, 0, 1, 4, 5, 3 },
00039 };
00040
00041 static av_cold int Faac_encode_init(AVCodecContext *avctx)
00042 {
00043 FaacAudioContext *s = avctx->priv_data;
00044 faacEncConfigurationPtr faac_cfg;
00045 unsigned long samples_input, max_bytes_output;
00046
00047
00048 if (avctx->channels < 1 || avctx->channels > 6) {
00049 av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels);
00050 return -1;
00051 }
00052
00053 s->faac_handle = faacEncOpen(avctx->sample_rate,
00054 avctx->channels,
00055 &samples_input, &max_bytes_output);
00056
00057
00058 faac_cfg = faacEncGetCurrentConfiguration(s->faac_handle);
00059 if (faac_cfg->version != FAAC_CFG_VERSION) {
00060 av_log(avctx, AV_LOG_ERROR, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION, faac_cfg->version);
00061 faacEncClose(s->faac_handle);
00062 return -1;
00063 }
00064
00065
00066 switch(avctx->profile) {
00067 case FF_PROFILE_AAC_MAIN:
00068 faac_cfg->aacObjectType = MAIN;
00069 break;
00070 case FF_PROFILE_UNKNOWN:
00071 case FF_PROFILE_AAC_LOW:
00072 faac_cfg->aacObjectType = LOW;
00073 break;
00074 case FF_PROFILE_AAC_SSR:
00075 faac_cfg->aacObjectType = SSR;
00076 break;
00077 case FF_PROFILE_AAC_LTP:
00078 faac_cfg->aacObjectType = LTP;
00079 break;
00080 default:
00081 av_log(avctx, AV_LOG_ERROR, "invalid AAC profile\n");
00082 faacEncClose(s->faac_handle);
00083 return -1;
00084 }
00085 faac_cfg->mpegVersion = MPEG4;
00086 faac_cfg->useTns = 0;
00087 faac_cfg->allowMidside = 1;
00088 faac_cfg->bitRate = avctx->bit_rate / avctx->channels;
00089 faac_cfg->bandWidth = avctx->cutoff;
00090 if(avctx->flags & CODEC_FLAG_QSCALE) {
00091 faac_cfg->bitRate = 0;
00092 faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA;
00093 }
00094 faac_cfg->outputFormat = 1;
00095 faac_cfg->inputFormat = FAAC_INPUT_16BIT;
00096 if (avctx->channels > 2)
00097 memcpy(faac_cfg->channel_map, channel_maps[avctx->channels-3],
00098 avctx->channels * sizeof(int));
00099
00100 avctx->frame_size = samples_input / avctx->channels;
00101
00102 avctx->coded_frame= avcodec_alloc_frame();
00103 avctx->coded_frame->key_frame= 1;
00104
00105
00106 avctx->extradata_size = 0;
00107 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
00108
00109 unsigned char *buffer = NULL;
00110 unsigned long decoder_specific_info_size;
00111
00112 if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer,
00113 &decoder_specific_info_size)) {
00114 avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE);
00115 avctx->extradata_size = decoder_specific_info_size;
00116 memcpy(avctx->extradata, buffer, avctx->extradata_size);
00117 faac_cfg->outputFormat = 0;
00118 }
00119 #undef free
00120 free(buffer);
00121 #define free please_use_av_free
00122 }
00123
00124 if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) {
00125 av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n");
00126 return -1;
00127 }
00128
00129 return 0;
00130 }
00131
00132 static int Faac_encode_frame(AVCodecContext *avctx,
00133 unsigned char *frame, int buf_size, void *data)
00134 {
00135 FaacAudioContext *s = avctx->priv_data;
00136 int bytes_written;
00137 int num_samples = data ? avctx->frame_size : 0;
00138
00139 bytes_written = faacEncEncode(s->faac_handle,
00140 data,
00141 num_samples * avctx->channels,
00142 frame,
00143 buf_size);
00144
00145 return bytes_written;
00146 }
00147
00148 static av_cold int Faac_encode_close(AVCodecContext *avctx)
00149 {
00150 FaacAudioContext *s = avctx->priv_data;
00151
00152 av_freep(&avctx->coded_frame);
00153 av_freep(&avctx->extradata);
00154
00155 faacEncClose(s->faac_handle);
00156 return 0;
00157 }
00158
00159 static const AVProfile profiles[] = {
00160 { FF_PROFILE_AAC_MAIN, "Main" },
00161 { FF_PROFILE_AAC_LOW, "LC" },
00162 { FF_PROFILE_AAC_SSR, "SSR" },
00163 { FF_PROFILE_AAC_LTP, "LTP" },
00164 { FF_PROFILE_UNKNOWN },
00165 };
00166
00167 AVCodec ff_libfaac_encoder = {
00168 .name = "libfaac",
00169 .type = AVMEDIA_TYPE_AUDIO,
00170 .id = CODEC_ID_AAC,
00171 .priv_data_size = sizeof(FaacAudioContext),
00172 .init = Faac_encode_init,
00173 .encode = Faac_encode_frame,
00174 .close = Faac_encode_close,
00175 .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY,
00176 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
00177 .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Codec)"),
00178 .profiles = NULL_IF_CONFIG_SMALL(profiles),
00179 };