00001 /* 00002 * Interface to libaacplus for aac+ (sbr+ps) encoding 00003 * Copyright (c) 2010 tipok <piratfm@gmail.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 <aacplus.h> 00029 00030 typedef struct aacPlusAudioContext { 00031 aacplusEncHandle aacplus_handle; 00032 } aacPlusAudioContext; 00033 00034 static av_cold int aacPlus_encode_init(AVCodecContext *avctx) 00035 { 00036 aacPlusAudioContext *s = avctx->priv_data; 00037 aacplusEncConfiguration *aacplus_cfg; 00038 unsigned long samples_input, max_bytes_output; 00039 00040 /* number of channels */ 00041 if (avctx->channels < 1 || avctx->channels > 2) { 00042 av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels); 00043 return -1; 00044 } 00045 00046 s->aacplus_handle = aacplusEncOpen(avctx->sample_rate, 00047 avctx->channels, 00048 &samples_input, &max_bytes_output); 00049 if(!s->aacplus_handle) { 00050 av_log(avctx, AV_LOG_ERROR, "can't open encoder\n"); 00051 return -1; 00052 } 00053 00054 /* check aacplus version */ 00055 aacplus_cfg = aacplusEncGetCurrentConfiguration(s->aacplus_handle); 00056 00057 /* put the options in the configuration struct */ 00058 if(avctx->profile != FF_PROFILE_AAC_LOW && avctx->profile != FF_PROFILE_UNKNOWN) { 00059 av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC supported\n", avctx->profile); 00060 aacplusEncClose(s->aacplus_handle); 00061 return -1; 00062 } 00063 00064 aacplus_cfg->bitRate = avctx->bit_rate; 00065 aacplus_cfg->bandWidth = avctx->cutoff; 00066 aacplus_cfg->outputFormat = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER); 00067 aacplus_cfg->inputFormat = AACPLUS_INPUT_16BIT; 00068 if (!aacplusEncSetConfiguration(s->aacplus_handle, aacplus_cfg)) { 00069 av_log(avctx, AV_LOG_ERROR, "libaacplus doesn't support this output format!\n"); 00070 return -1; 00071 } 00072 00073 avctx->frame_size = samples_input / avctx->channels; 00074 00075 avctx->coded_frame= avcodec_alloc_frame(); 00076 avctx->coded_frame->key_frame= 1; 00077 00078 /* Set decoder specific info */ 00079 avctx->extradata_size = 0; 00080 if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { 00081 00082 unsigned char *buffer = NULL; 00083 unsigned long decoder_specific_info_size; 00084 00085 if (aacplusEncGetDecoderSpecificInfo(s->aacplus_handle, &buffer, 00086 &decoder_specific_info_size) == 1) { 00087 avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); 00088 avctx->extradata_size = decoder_specific_info_size; 00089 memcpy(avctx->extradata, buffer, avctx->extradata_size); 00090 } 00091 #undef free 00092 free(buffer); 00093 #define free please_use_av_free 00094 } 00095 return 0; 00096 } 00097 00098 static int aacPlus_encode_frame(AVCodecContext *avctx, 00099 unsigned char *frame, int buf_size, void *data) 00100 { 00101 aacPlusAudioContext *s = avctx->priv_data; 00102 int bytes_written; 00103 00104 bytes_written = aacplusEncEncode(s->aacplus_handle, 00105 data, 00106 avctx->frame_size * avctx->channels, 00107 frame, 00108 buf_size); 00109 00110 return bytes_written; 00111 } 00112 00113 static av_cold int aacPlus_encode_close(AVCodecContext *avctx) 00114 { 00115 aacPlusAudioContext *s = avctx->priv_data; 00116 00117 av_freep(&avctx->coded_frame); 00118 av_freep(&avctx->extradata); 00119 00120 aacplusEncClose(s->aacplus_handle); 00121 return 0; 00122 } 00123 00124 AVCodec ff_libaacplus_encoder = { 00125 "libaacplus", 00126 AVMEDIA_TYPE_AUDIO, 00127 CODEC_ID_AAC, 00128 sizeof(aacPlusAudioContext), 00129 aacPlus_encode_init, 00130 aacPlus_encode_frame, 00131 aacPlus_encode_close, 00132 .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, 00133 .long_name = NULL_IF_CONFIG_SMALL("libaacplus AAC+ (Advanced Audio Codec with SBR+PS)"), 00134 };