libavcodec/libaacplus.c
Go to the documentation of this file.
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     .name           = "libaacplus",
00126     .type           = AVMEDIA_TYPE_AUDIO,
00127     .id             = CODEC_ID_AAC,
00128     .priv_data_size = sizeof(aacPlusAudioContext),
00129     .init           = aacPlus_encode_init,
00130     .encode         = aacPlus_encode_frame,
00131     .close          = aacPlus_encode_close,
00132     .sample_fmts = (const enum SampleFormat[]){AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE},
00133     .long_name = NULL_IF_CONFIG_SMALL("libaacplus AAC+ (Advanced Audio Codec with SBR+PS)"),
00134 };