2 * Interface to libfaac for aac encoding
3 * Copyright (c) 2002 Gildas Bazin <gbazin@netcourrier.com>
5 * This file is part of Libav.
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.
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.
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
24 * Interface to libfaac for aac encoding.
29 #include "libavutil/channel_layout.h"
30 #include "libavutil/common.h"
32 #include "audio_frame_queue.h"
36 /* libfaac has an encoder delay of 1024 samples */
37 #define FAAC_DELAY_SAMPLES 1024
39 typedef struct FaacAudioContext
{
40 faacEncHandle faac_handle
;
45 static av_cold
int Faac_encode_close(AVCodecContext
*avctx
)
47 FaacAudioContext
*s
= avctx
->priv_data
;
49 #if FF_API_OLD_ENCODE_AUDIO
50 av_freep(&avctx
->coded_frame
);
52 av_freep(&avctx
->extradata
);
53 ff_af_queue_close(&s
->afq
);
56 faacEncClose(s
->faac_handle
);
61 static const int channel_maps
[][6] = {
62 { 2, 0, 1 }, //< C L R
63 { 2, 0, 1, 3 }, //< C L R Cs
64 { 2, 0, 1, 3, 4 }, //< C L R Ls Rs
65 { 2, 0, 1, 4, 5, 3 }, //< C L R Ls Rs LFE
68 static av_cold
int Faac_encode_init(AVCodecContext
*avctx
)
70 FaacAudioContext
*s
= avctx
->priv_data
;
71 faacEncConfigurationPtr faac_cfg
;
72 unsigned long samples_input
, max_bytes_output
;
75 /* number of channels */
76 if (avctx
->channels
< 1 || avctx
->channels
> 6) {
77 av_log(avctx
, AV_LOG_ERROR
, "encoding %d channel(s) is not allowed\n", avctx
->channels
);
78 ret
= AVERROR(EINVAL
);
82 s
->faac_handle
= faacEncOpen(avctx
->sample_rate
,
84 &samples_input
, &max_bytes_output
);
85 if (!s
->faac_handle
) {
86 av_log(avctx
, AV_LOG_ERROR
, "error in faacEncOpen()\n");
87 ret
= AVERROR_UNKNOWN
;
91 /* check faac version */
92 faac_cfg
= faacEncGetCurrentConfiguration(s
->faac_handle
);
93 if (faac_cfg
->version
!= FAAC_CFG_VERSION
) {
94 av_log(avctx
, AV_LOG_ERROR
, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION
, faac_cfg
->version
);
95 ret
= AVERROR(EINVAL
);
99 /* put the options in the configuration struct */
100 switch(avctx
->profile
) {
101 case FF_PROFILE_AAC_MAIN
:
102 faac_cfg
->aacObjectType
= MAIN
;
104 case FF_PROFILE_UNKNOWN
:
105 case FF_PROFILE_AAC_LOW
:
106 faac_cfg
->aacObjectType
= LOW
;
108 case FF_PROFILE_AAC_SSR
:
109 faac_cfg
->aacObjectType
= SSR
;
111 case FF_PROFILE_AAC_LTP
:
112 faac_cfg
->aacObjectType
= LTP
;
115 av_log(avctx
, AV_LOG_ERROR
, "invalid AAC profile\n");
116 ret
= AVERROR(EINVAL
);
119 faac_cfg
->mpegVersion
= MPEG4
;
120 faac_cfg
->useTns
= 0;
121 faac_cfg
->allowMidside
= 1;
122 faac_cfg
->bitRate
= avctx
->bit_rate
/ avctx
->channels
;
123 faac_cfg
->bandWidth
= avctx
->cutoff
;
124 if(avctx
->flags
& CODEC_FLAG_QSCALE
) {
125 faac_cfg
->bitRate
= 0;
126 faac_cfg
->quantqual
= avctx
->global_quality
/ FF_QP2LAMBDA
;
128 faac_cfg
->outputFormat
= 1;
129 faac_cfg
->inputFormat
= FAAC_INPUT_16BIT
;
130 if (avctx
->channels
> 2)
131 memcpy(faac_cfg
->channel_map
, channel_maps
[avctx
->channels
-3],
132 avctx
->channels
* sizeof(int));
134 avctx
->frame_size
= samples_input
/ avctx
->channels
;
136 #if FF_API_OLD_ENCODE_AUDIO
137 avctx
->coded_frame
= avcodec_alloc_frame();
138 if (!avctx
->coded_frame
) {
139 ret
= AVERROR(ENOMEM
);
144 /* Set decoder specific info */
145 avctx
->extradata_size
= 0;
146 if (avctx
->flags
& CODEC_FLAG_GLOBAL_HEADER
) {
148 unsigned char *buffer
= NULL
;
149 unsigned long decoder_specific_info_size
;
151 if (!faacEncGetDecoderSpecificInfo(s
->faac_handle
, &buffer
,
152 &decoder_specific_info_size
)) {
153 avctx
->extradata
= av_malloc(decoder_specific_info_size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
154 if (!avctx
->extradata
) {
155 ret
= AVERROR(ENOMEM
);
158 avctx
->extradata_size
= decoder_specific_info_size
;
159 memcpy(avctx
->extradata
, buffer
, avctx
->extradata_size
);
160 faac_cfg
->outputFormat
= 0;
165 if (!faacEncSetConfiguration(s
->faac_handle
, faac_cfg
)) {
166 av_log(avctx
, AV_LOG_ERROR
, "libfaac doesn't support this output format!\n");
167 ret
= AVERROR(EINVAL
);
171 avctx
->delay
= FAAC_DELAY_SAMPLES
;
172 ff_af_queue_init(avctx
, &s
->afq
);
176 Faac_encode_close(avctx
);
180 static int Faac_encode_frame(AVCodecContext
*avctx
, AVPacket
*avpkt
,
181 const AVFrame
*frame
, int *got_packet_ptr
)
183 FaacAudioContext
*s
= avctx
->priv_data
;
184 int bytes_written
, ret
;
185 int num_samples
= frame
? frame
->nb_samples
: 0;
186 void *samples
= frame
? frame
->data
[0] : NULL
;
188 if ((ret
= ff_alloc_packet(avpkt
, (7 + 768) * avctx
->channels
))) {
189 av_log(avctx
, AV_LOG_ERROR
, "Error getting output packet\n");
193 bytes_written
= faacEncEncode(s
->faac_handle
, samples
,
194 num_samples
* avctx
->channels
,
195 avpkt
->data
, avpkt
->size
);
196 if (bytes_written
< 0) {
197 av_log(avctx
, AV_LOG_ERROR
, "faacEncEncode() error\n");
198 return bytes_written
;
201 /* add current frame to the queue */
203 if ((ret
= ff_af_queue_add(&s
->afq
, frame
)) < 0)
210 /* Get the next frame pts/duration */
211 ff_af_queue_remove(&s
->afq
, avctx
->frame_size
, &avpkt
->pts
,
214 avpkt
->size
= bytes_written
;
219 static const AVProfile profiles
[] = {
220 { FF_PROFILE_AAC_MAIN
, "Main" },
221 { FF_PROFILE_AAC_LOW
, "LC" },
222 { FF_PROFILE_AAC_SSR
, "SSR" },
223 { FF_PROFILE_AAC_LTP
, "LTP" },
224 { FF_PROFILE_UNKNOWN
},
227 static const uint64_t faac_channel_layouts
[] = {
230 AV_CH_LAYOUT_SURROUND
,
231 AV_CH_LAYOUT_4POINT0
,
232 AV_CH_LAYOUT_5POINT0_BACK
,
233 AV_CH_LAYOUT_5POINT1_BACK
,
237 AVCodec ff_libfaac_encoder
= {
239 .type
= AVMEDIA_TYPE_AUDIO
,
240 .id
= AV_CODEC_ID_AAC
,
241 .priv_data_size
= sizeof(FaacAudioContext
),
242 .init
= Faac_encode_init
,
243 .encode2
= Faac_encode_frame
,
244 .close
= Faac_encode_close
,
245 .capabilities
= CODEC_CAP_SMALL_LAST_FRAME
| CODEC_CAP_DELAY
,
246 .sample_fmts
= (const enum AVSampleFormat
[]){ AV_SAMPLE_FMT_S16
,
247 AV_SAMPLE_FMT_NONE
},
248 .long_name
= NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Coding)"),
249 .profiles
= NULL_IF_CONFIG_SMALL(profiles
),
250 .channel_layouts
= faac_channel_layouts
,