Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * AAC decoder wrapper | |
3 | * Copyright (c) 2012 Martin Storsjo | |
4 | * | |
5 | * This file is part of FFmpeg. | |
6 | * | |
7 | * Permission to use, copy, modify, and/or distribute this software for any | |
8 | * purpose with or without fee is hereby granted, provided that the above | |
9 | * copyright notice and this permission notice appear in all copies. | |
10 | * | |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
18 | */ | |
19 | ||
20 | #include <fdk-aac/aacdecoder_lib.h> | |
21 | ||
22 | #include "libavutil/channel_layout.h" | |
23 | #include "libavutil/common.h" | |
24 | #include "libavutil/opt.h" | |
25 | #include "avcodec.h" | |
26 | #include "internal.h" | |
27 | ||
f6fa7814 DM |
28 | /* The version macro is introduced the same time as the setting enum was |
29 | * changed, so this check should suffice. */ | |
30 | #ifndef AACDECODER_LIB_VL0 | |
31 | #define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS | |
32 | #endif | |
33 | ||
2ba45a60 DM |
34 | enum ConcealMethod { |
35 | CONCEAL_METHOD_SPECTRAL_MUTING = 0, | |
36 | CONCEAL_METHOD_NOISE_SUBSTITUTION = 1, | |
37 | CONCEAL_METHOD_ENERGY_INTERPOLATION = 2, | |
38 | CONCEAL_METHOD_NB, | |
39 | }; | |
40 | ||
41 | typedef struct FDKAACDecContext { | |
42 | const AVClass *class; | |
43 | HANDLE_AACDECODER handle; | |
44 | int initialized; | |
f6fa7814 DM |
45 | uint8_t *decoder_buffer; |
46 | uint8_t *anc_buffer; | |
2ba45a60 | 47 | enum ConcealMethod conceal_method; |
f6fa7814 DM |
48 | int drc_level; |
49 | int drc_boost; | |
50 | int drc_heavy; | |
51 | int drc_cut; | |
2ba45a60 DM |
52 | } FDKAACDecContext; |
53 | ||
f6fa7814 DM |
54 | |
55 | #define DMX_ANC_BUFFSIZE 128 | |
56 | #define DECODER_MAX_CHANNELS 6 | |
57 | #define DECODER_BUFFSIZE 2048 * sizeof(INT_PCM) | |
58 | ||
2ba45a60 DM |
59 | #define OFFSET(x) offsetof(FDKAACDecContext, x) |
60 | #define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM | |
61 | static const AVOption fdk_aac_dec_options[] = { | |
62 | { "conceal", "Error concealment method", OFFSET(conceal_method), AV_OPT_TYPE_INT, { .i64 = CONCEAL_METHOD_NOISE_SUBSTITUTION }, CONCEAL_METHOD_SPECTRAL_MUTING, CONCEAL_METHOD_NB - 1, AD, "conceal" }, | |
63 | { "spectral", "Spectral muting", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_SPECTRAL_MUTING }, INT_MIN, INT_MAX, AD, "conceal" }, | |
64 | { "noise", "Noise Substitution", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_NOISE_SUBSTITUTION }, INT_MIN, INT_MAX, AD, "conceal" }, | |
65 | { "energy", "Energy Interpolation", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_ENERGY_INTERPOLATION }, INT_MIN, INT_MAX, AD, "conceal" }, | |
f6fa7814 DM |
66 | { "drc_boost", "Dynamic Range Control: boost, where [0] is none and [127] is max boost", |
67 | OFFSET(drc_boost), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, | |
68 | { "drc_cut", "Dynamic Range Control: attenuation factor, where [0] is none and [127] is max compression", | |
69 | OFFSET(drc_cut), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, | |
70 | { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB", | |
71 | OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, | |
72 | { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", | |
73 | OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, | |
2ba45a60 DM |
74 | { NULL } |
75 | }; | |
76 | ||
77 | static const AVClass fdk_aac_dec_class = { | |
78 | "libfdk-aac decoder", av_default_item_name, fdk_aac_dec_options, LIBAVUTIL_VERSION_INT | |
79 | }; | |
80 | ||
81 | static int get_stream_info(AVCodecContext *avctx) | |
82 | { | |
83 | FDKAACDecContext *s = avctx->priv_data; | |
84 | CStreamInfo *info = aacDecoder_GetStreamInfo(s->handle); | |
f6fa7814 | 85 | int channel_counts[0x24] = { 0 }; |
2ba45a60 DM |
86 | int i, ch_error = 0; |
87 | uint64_t ch_layout = 0; | |
88 | ||
89 | if (!info) { | |
90 | av_log(avctx, AV_LOG_ERROR, "Unable to get stream info\n"); | |
91 | return AVERROR_UNKNOWN; | |
92 | } | |
93 | ||
94 | if (info->sampleRate <= 0) { | |
95 | av_log(avctx, AV_LOG_ERROR, "Stream info not initialized\n"); | |
96 | return AVERROR_UNKNOWN; | |
97 | } | |
98 | avctx->sample_rate = info->sampleRate; | |
99 | avctx->frame_size = info->frameSize; | |
100 | ||
101 | for (i = 0; i < info->numChannels; i++) { | |
102 | AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i]; | |
f6fa7814 | 103 | if (ctype <= ACT_NONE || ctype > FF_ARRAY_ELEMS(channel_counts)) { |
2ba45a60 DM |
104 | av_log(avctx, AV_LOG_WARNING, "unknown channel type\n"); |
105 | break; | |
106 | } | |
107 | channel_counts[ctype]++; | |
108 | } | |
109 | av_log(avctx, AV_LOG_DEBUG, | |
110 | "%d channels - front:%d side:%d back:%d lfe:%d top:%d\n", | |
111 | info->numChannels, | |
112 | channel_counts[ACT_FRONT], channel_counts[ACT_SIDE], | |
113 | channel_counts[ACT_BACK], channel_counts[ACT_LFE], | |
114 | channel_counts[ACT_FRONT_TOP] + channel_counts[ACT_SIDE_TOP] + | |
115 | channel_counts[ACT_BACK_TOP] + channel_counts[ACT_TOP]); | |
116 | ||
117 | switch (channel_counts[ACT_FRONT]) { | |
118 | case 4: | |
119 | ch_layout |= AV_CH_LAYOUT_STEREO | AV_CH_FRONT_LEFT_OF_CENTER | | |
120 | AV_CH_FRONT_RIGHT_OF_CENTER; | |
121 | break; | |
122 | case 3: | |
123 | ch_layout |= AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER; | |
124 | break; | |
125 | case 2: | |
126 | ch_layout |= AV_CH_LAYOUT_STEREO; | |
127 | break; | |
128 | case 1: | |
129 | ch_layout |= AV_CH_FRONT_CENTER; | |
130 | break; | |
131 | default: | |
132 | av_log(avctx, AV_LOG_WARNING, | |
133 | "unsupported number of front channels: %d\n", | |
134 | channel_counts[ACT_FRONT]); | |
135 | ch_error = 1; | |
136 | break; | |
137 | } | |
138 | if (channel_counts[ACT_SIDE] > 0) { | |
139 | if (channel_counts[ACT_SIDE] == 2) { | |
140 | ch_layout |= AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT; | |
141 | } else { | |
142 | av_log(avctx, AV_LOG_WARNING, | |
143 | "unsupported number of side channels: %d\n", | |
144 | channel_counts[ACT_SIDE]); | |
145 | ch_error = 1; | |
146 | } | |
147 | } | |
148 | if (channel_counts[ACT_BACK] > 0) { | |
149 | switch (channel_counts[ACT_BACK]) { | |
150 | case 3: | |
151 | ch_layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_BACK_CENTER; | |
152 | break; | |
153 | case 2: | |
154 | ch_layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT; | |
155 | break; | |
156 | case 1: | |
157 | ch_layout |= AV_CH_BACK_CENTER; | |
158 | break; | |
159 | default: | |
160 | av_log(avctx, AV_LOG_WARNING, | |
161 | "unsupported number of back channels: %d\n", | |
162 | channel_counts[ACT_BACK]); | |
163 | ch_error = 1; | |
164 | break; | |
165 | } | |
166 | } | |
167 | if (channel_counts[ACT_LFE] > 0) { | |
168 | if (channel_counts[ACT_LFE] == 1) { | |
169 | ch_layout |= AV_CH_LOW_FREQUENCY; | |
170 | } else { | |
171 | av_log(avctx, AV_LOG_WARNING, | |
172 | "unsupported number of LFE channels: %d\n", | |
173 | channel_counts[ACT_LFE]); | |
174 | ch_error = 1; | |
175 | } | |
176 | } | |
177 | if (!ch_error && | |
178 | av_get_channel_layout_nb_channels(ch_layout) != info->numChannels) { | |
179 | av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n"); | |
180 | ch_error = 1; | |
181 | } | |
182 | if (ch_error) | |
183 | avctx->channel_layout = 0; | |
184 | else | |
185 | avctx->channel_layout = ch_layout; | |
186 | ||
187 | avctx->channels = info->numChannels; | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
192 | static av_cold int fdk_aac_decode_close(AVCodecContext *avctx) | |
193 | { | |
194 | FDKAACDecContext *s = avctx->priv_data; | |
195 | ||
196 | if (s->handle) | |
197 | aacDecoder_Close(s->handle); | |
f6fa7814 DM |
198 | av_freep(&s->decoder_buffer); |
199 | av_freep(&s->anc_buffer); | |
2ba45a60 DM |
200 | |
201 | return 0; | |
202 | } | |
203 | ||
204 | static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) | |
205 | { | |
206 | FDKAACDecContext *s = avctx->priv_data; | |
207 | AAC_DECODER_ERROR err; | |
f6fa7814 | 208 | int ret; |
2ba45a60 DM |
209 | |
210 | s->handle = aacDecoder_Open(avctx->extradata_size ? TT_MP4_RAW : TT_MP4_ADTS, 1); | |
211 | if (!s->handle) { | |
212 | av_log(avctx, AV_LOG_ERROR, "Error opening decoder\n"); | |
213 | return AVERROR_UNKNOWN; | |
214 | } | |
215 | ||
216 | if (avctx->extradata_size) { | |
217 | if ((err = aacDecoder_ConfigRaw(s->handle, &avctx->extradata, | |
218 | &avctx->extradata_size)) != AAC_DEC_OK) { | |
219 | av_log(avctx, AV_LOG_ERROR, "Unable to set extradata\n"); | |
220 | return AVERROR_INVALIDDATA; | |
221 | } | |
222 | } | |
223 | ||
224 | if ((err = aacDecoder_SetParam(s->handle, AAC_CONCEAL_METHOD, | |
225 | s->conceal_method)) != AAC_DEC_OK) { | |
226 | av_log(avctx, AV_LOG_ERROR, "Unable to set error concealment method\n"); | |
227 | return AVERROR_UNKNOWN; | |
228 | } | |
229 | ||
f6fa7814 DM |
230 | if (avctx->request_channel_layout > 0 && |
231 | avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) { | |
232 | int downmix_channels = -1; | |
233 | ||
234 | switch (avctx->request_channel_layout) { | |
235 | case AV_CH_LAYOUT_STEREO: | |
236 | case AV_CH_LAYOUT_STEREO_DOWNMIX: | |
237 | downmix_channels = 2; | |
238 | break; | |
239 | case AV_CH_LAYOUT_MONO: | |
240 | downmix_channels = 1; | |
241 | break; | |
242 | default: | |
243 | av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); | |
244 | break; | |
245 | } | |
246 | ||
247 | if (downmix_channels != -1) { | |
248 | if (aacDecoder_SetParam(s->handle, AAC_PCM_MAX_OUTPUT_CHANNELS, | |
249 | downmix_channels) != AAC_DEC_OK) { | |
250 | av_log(avctx, AV_LOG_WARNING, "Unable to set output channels in the decoder\n"); | |
251 | } else { | |
252 | s->anc_buffer = av_malloc(DMX_ANC_BUFFSIZE); | |
253 | if (!s->anc_buffer) { | |
254 | av_log(avctx, AV_LOG_ERROR, "Unable to allocate ancillary buffer for the decoder\n"); | |
255 | ret = AVERROR(ENOMEM); | |
256 | goto fail; | |
257 | } | |
258 | if (aacDecoder_AncDataInit(s->handle, s->anc_buffer, DMX_ANC_BUFFSIZE)) { | |
259 | av_log(avctx, AV_LOG_ERROR, "Unable to register downmix ancillary buffer in the decoder\n"); | |
260 | ret = AVERROR_UNKNOWN; | |
261 | goto fail; | |
262 | } | |
263 | } | |
264 | } | |
265 | } | |
266 | ||
267 | if (s->drc_boost != -1) { | |
268 | if (aacDecoder_SetParam(s->handle, AAC_DRC_BOOST_FACTOR, s->drc_boost) != AAC_DEC_OK) { | |
269 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC boost factor in the decoder\n"); | |
270 | return AVERROR_UNKNOWN; | |
271 | } | |
272 | } | |
273 | ||
274 | if (s->drc_cut != -1) { | |
275 | if (aacDecoder_SetParam(s->handle, AAC_DRC_ATTENUATION_FACTOR, s->drc_cut) != AAC_DEC_OK) { | |
276 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC attenuation factor in the decoder\n"); | |
277 | return AVERROR_UNKNOWN; | |
278 | } | |
279 | } | |
280 | ||
281 | if (s->drc_level != -1) { | |
282 | if (aacDecoder_SetParam(s->handle, AAC_DRC_REFERENCE_LEVEL, s->drc_level) != AAC_DEC_OK) { | |
283 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC reference level in the decoder\n"); | |
284 | return AVERROR_UNKNOWN; | |
285 | } | |
286 | } | |
287 | ||
288 | if (s->drc_heavy != -1) { | |
289 | if (aacDecoder_SetParam(s->handle, AAC_DRC_HEAVY_COMPRESSION, s->drc_heavy) != AAC_DEC_OK) { | |
290 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC heavy compression in the decoder\n"); | |
291 | return AVERROR_UNKNOWN; | |
292 | } | |
293 | } | |
294 | ||
2ba45a60 DM |
295 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
296 | ||
297 | return 0; | |
f6fa7814 DM |
298 | fail: |
299 | fdk_aac_decode_close(avctx); | |
300 | return ret; | |
2ba45a60 DM |
301 | } |
302 | ||
303 | static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, | |
304 | int *got_frame_ptr, AVPacket *avpkt) | |
305 | { | |
306 | FDKAACDecContext *s = avctx->priv_data; | |
307 | AVFrame *frame = data; | |
308 | int ret; | |
309 | AAC_DECODER_ERROR err; | |
310 | UINT valid = avpkt->size; | |
311 | uint8_t *buf, *tmpptr = NULL; | |
312 | int buf_size; | |
313 | ||
314 | err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); | |
315 | if (err != AAC_DEC_OK) { | |
316 | av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); | |
317 | return AVERROR_INVALIDDATA; | |
318 | } | |
319 | ||
320 | if (s->initialized) { | |
321 | frame->nb_samples = avctx->frame_size; | |
322 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
323 | return ret; | |
f6fa7814 DM |
324 | |
325 | if (s->anc_buffer) { | |
326 | buf_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; | |
327 | buf = s->decoder_buffer; | |
328 | } else { | |
329 | buf = frame->extended_data[0]; | |
330 | buf_size = avctx->channels * frame->nb_samples * | |
331 | av_get_bytes_per_sample(avctx->sample_fmt); | |
332 | } | |
2ba45a60 | 333 | } else { |
f6fa7814 DM |
334 | buf_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; |
335 | ||
336 | if (!s->decoder_buffer) | |
337 | s->decoder_buffer = av_malloc(buf_size); | |
338 | if (!s->decoder_buffer) | |
2ba45a60 | 339 | return AVERROR(ENOMEM); |
f6fa7814 DM |
340 | |
341 | buf = tmpptr = s->decoder_buffer; | |
2ba45a60 DM |
342 | } |
343 | ||
344 | err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) buf, buf_size, 0); | |
345 | if (err == AAC_DEC_NOT_ENOUGH_BITS) { | |
346 | ret = avpkt->size - valid; | |
347 | goto end; | |
348 | } | |
349 | if (err != AAC_DEC_OK) { | |
350 | av_log(avctx, AV_LOG_ERROR, | |
351 | "aacDecoder_DecodeFrame() failed: %x\n", err); | |
352 | ret = AVERROR_UNKNOWN; | |
353 | goto end; | |
354 | } | |
355 | ||
356 | if (!s->initialized) { | |
357 | if ((ret = get_stream_info(avctx)) < 0) | |
358 | goto end; | |
359 | s->initialized = 1; | |
360 | frame->nb_samples = avctx->frame_size; | |
361 | } | |
362 | ||
363 | if (tmpptr) { | |
364 | frame->nb_samples = avctx->frame_size; | |
365 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
366 | goto end; | |
f6fa7814 DM |
367 | } |
368 | if (s->decoder_buffer) { | |
369 | memcpy(frame->extended_data[0], buf, | |
2ba45a60 DM |
370 | avctx->channels * avctx->frame_size * |
371 | av_get_bytes_per_sample(avctx->sample_fmt)); | |
f6fa7814 DM |
372 | |
373 | if (!s->anc_buffer) | |
374 | av_freep(&s->decoder_buffer); | |
2ba45a60 DM |
375 | } |
376 | ||
377 | *got_frame_ptr = 1; | |
378 | ret = avpkt->size - valid; | |
379 | ||
380 | end: | |
2ba45a60 DM |
381 | return ret; |
382 | } | |
383 | ||
384 | static av_cold void fdk_aac_decode_flush(AVCodecContext *avctx) | |
385 | { | |
386 | FDKAACDecContext *s = avctx->priv_data; | |
387 | AAC_DECODER_ERROR err; | |
388 | ||
389 | if (!s->handle) | |
390 | return; | |
391 | ||
392 | if ((err = aacDecoder_SetParam(s->handle, | |
393 | AAC_TPDEC_CLEAR_BUFFER, 1)) != AAC_DEC_OK) | |
394 | av_log(avctx, AV_LOG_WARNING, "failed to clear buffer when flushing\n"); | |
395 | } | |
396 | ||
397 | AVCodec ff_libfdk_aac_decoder = { | |
398 | .name = "libfdk_aac", | |
399 | .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), | |
400 | .type = AVMEDIA_TYPE_AUDIO, | |
401 | .id = AV_CODEC_ID_AAC, | |
402 | .priv_data_size = sizeof(FDKAACDecContext), | |
403 | .init = fdk_aac_decode_init, | |
404 | .decode = fdk_aac_decode_frame, | |
405 | .close = fdk_aac_decode_close, | |
406 | .flush = fdk_aac_decode_flush, | |
407 | .capabilities = CODEC_CAP_DR1 | CODEC_CAP_CHANNEL_CONF, | |
408 | .priv_class = &fdk_aac_dec_class, | |
409 | }; |