blob: e5f7c4ebdc97330dba71761fed2e1bee1c4c8139
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 | |
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 | |
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 | uint8_t *decoder_buffer; |
45 | int decoder_buffer_size; |
46 | uint8_t *anc_buffer; |
47 | int conceal_method; |
48 | int drc_level; |
49 | int drc_boost; |
50 | int drc_heavy; |
51 | int drc_cut; |
52 | int level_limit; |
53 | } FDKAACDecContext; |
54 | |
55 | |
56 | #define DMX_ANC_BUFFSIZE 128 |
57 | #define DECODER_MAX_CHANNELS 8 |
58 | #define DECODER_BUFFSIZE 2048 * sizeof(INT_PCM) |
59 | |
60 | #define OFFSET(x) offsetof(FDKAACDecContext, x) |
61 | #define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM |
62 | static const AVOption fdk_aac_dec_options[] = { |
63 | { "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" }, |
64 | { "spectral", "Spectral muting", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_SPECTRAL_MUTING }, INT_MIN, INT_MAX, AD, "conceal" }, |
65 | { "noise", "Noise Substitution", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_NOISE_SUBSTITUTION }, INT_MIN, INT_MAX, AD, "conceal" }, |
66 | { "energy", "Energy Interpolation", 0, AV_OPT_TYPE_CONST, { .i64 = CONCEAL_METHOD_ENERGY_INTERPOLATION }, INT_MIN, INT_MAX, AD, "conceal" }, |
67 | { "drc_boost", "Dynamic Range Control: boost, where [0] is none and [127] is max boost", |
68 | OFFSET(drc_boost), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, |
69 | { "drc_cut", "Dynamic Range Control: attenuation factor, where [0] is none and [127] is max compression", |
70 | OFFSET(drc_cut), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, |
71 | { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB", |
72 | OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, |
73 | { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", |
74 | OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, |
75 | #ifdef AACDECODER_LIB_VL0 |
76 | { "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD }, |
77 | #endif |
78 | { NULL } |
79 | }; |
80 | |
81 | static const AVClass fdk_aac_dec_class = { |
82 | "libfdk-aac decoder", av_default_item_name, fdk_aac_dec_options, LIBAVUTIL_VERSION_INT |
83 | }; |
84 | |
85 | static int get_stream_info(AVCodecContext *avctx) |
86 | { |
87 | FDKAACDecContext *s = avctx->priv_data; |
88 | CStreamInfo *info = aacDecoder_GetStreamInfo(s->handle); |
89 | int channel_counts[0x24] = { 0 }; |
90 | int i, ch_error = 0; |
91 | uint64_t ch_layout = 0; |
92 | |
93 | if (!info) { |
94 | av_log(avctx, AV_LOG_ERROR, "Unable to get stream info\n"); |
95 | return AVERROR_UNKNOWN; |
96 | } |
97 | |
98 | if (info->sampleRate <= 0) { |
99 | av_log(avctx, AV_LOG_ERROR, "Stream info not initialized\n"); |
100 | return AVERROR_UNKNOWN; |
101 | } |
102 | avctx->sample_rate = info->sampleRate; |
103 | avctx->frame_size = info->frameSize; |
104 | |
105 | for (i = 0; i < info->numChannels; i++) { |
106 | AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i]; |
107 | if (ctype <= ACT_NONE || ctype >= FF_ARRAY_ELEMS(channel_counts)) { |
108 | av_log(avctx, AV_LOG_WARNING, "unknown channel type\n"); |
109 | break; |
110 | } |
111 | channel_counts[ctype]++; |
112 | } |
113 | av_log(avctx, AV_LOG_DEBUG, |
114 | "%d channels - front:%d side:%d back:%d lfe:%d top:%d\n", |
115 | info->numChannels, |
116 | channel_counts[ACT_FRONT], channel_counts[ACT_SIDE], |
117 | channel_counts[ACT_BACK], channel_counts[ACT_LFE], |
118 | channel_counts[ACT_FRONT_TOP] + channel_counts[ACT_SIDE_TOP] + |
119 | channel_counts[ACT_BACK_TOP] + channel_counts[ACT_TOP]); |
120 | |
121 | switch (channel_counts[ACT_FRONT]) { |
122 | case 4: |
123 | ch_layout |= AV_CH_LAYOUT_STEREO | AV_CH_FRONT_LEFT_OF_CENTER | |
124 | AV_CH_FRONT_RIGHT_OF_CENTER; |
125 | break; |
126 | case 3: |
127 | ch_layout |= AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER; |
128 | break; |
129 | case 2: |
130 | ch_layout |= AV_CH_LAYOUT_STEREO; |
131 | break; |
132 | case 1: |
133 | ch_layout |= AV_CH_FRONT_CENTER; |
134 | break; |
135 | default: |
136 | av_log(avctx, AV_LOG_WARNING, |
137 | "unsupported number of front channels: %d\n", |
138 | channel_counts[ACT_FRONT]); |
139 | ch_error = 1; |
140 | break; |
141 | } |
142 | if (channel_counts[ACT_SIDE] > 0) { |
143 | if (channel_counts[ACT_SIDE] == 2) { |
144 | ch_layout |= AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT; |
145 | } else { |
146 | av_log(avctx, AV_LOG_WARNING, |
147 | "unsupported number of side channels: %d\n", |
148 | channel_counts[ACT_SIDE]); |
149 | ch_error = 1; |
150 | } |
151 | } |
152 | if (channel_counts[ACT_BACK] > 0) { |
153 | switch (channel_counts[ACT_BACK]) { |
154 | case 3: |
155 | ch_layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_BACK_CENTER; |
156 | break; |
157 | case 2: |
158 | ch_layout |= AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT; |
159 | break; |
160 | case 1: |
161 | ch_layout |= AV_CH_BACK_CENTER; |
162 | break; |
163 | default: |
164 | av_log(avctx, AV_LOG_WARNING, |
165 | "unsupported number of back channels: %d\n", |
166 | channel_counts[ACT_BACK]); |
167 | ch_error = 1; |
168 | break; |
169 | } |
170 | } |
171 | if (channel_counts[ACT_LFE] > 0) { |
172 | if (channel_counts[ACT_LFE] == 1) { |
173 | ch_layout |= AV_CH_LOW_FREQUENCY; |
174 | } else { |
175 | av_log(avctx, AV_LOG_WARNING, |
176 | "unsupported number of LFE channels: %d\n", |
177 | channel_counts[ACT_LFE]); |
178 | ch_error = 1; |
179 | } |
180 | } |
181 | if (!ch_error && |
182 | av_get_channel_layout_nb_channels(ch_layout) != info->numChannels) { |
183 | av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n"); |
184 | ch_error = 1; |
185 | } |
186 | if (ch_error) |
187 | avctx->channel_layout = 0; |
188 | else |
189 | avctx->channel_layout = ch_layout; |
190 | |
191 | avctx->channels = info->numChannels; |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | static av_cold int fdk_aac_decode_close(AVCodecContext *avctx) |
197 | { |
198 | FDKAACDecContext *s = avctx->priv_data; |
199 | |
200 | if (s->handle) |
201 | aacDecoder_Close(s->handle); |
202 | av_freep(&s->decoder_buffer); |
203 | av_freep(&s->anc_buffer); |
204 | |
205 | return 0; |
206 | } |
207 | |
208 | static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) |
209 | { |
210 | FDKAACDecContext *s = avctx->priv_data; |
211 | AAC_DECODER_ERROR err; |
212 | |
213 | s->handle = aacDecoder_Open(avctx->extradata_size ? TT_MP4_RAW : TT_MP4_ADTS, 1); |
214 | if (!s->handle) { |
215 | av_log(avctx, AV_LOG_ERROR, "Error opening decoder\n"); |
216 | return AVERROR_UNKNOWN; |
217 | } |
218 | |
219 | if (avctx->extradata_size) { |
220 | if ((err = aacDecoder_ConfigRaw(s->handle, &avctx->extradata, |
221 | &avctx->extradata_size)) != AAC_DEC_OK) { |
222 | av_log(avctx, AV_LOG_ERROR, "Unable to set extradata\n"); |
223 | return AVERROR_INVALIDDATA; |
224 | } |
225 | } |
226 | |
227 | if ((err = aacDecoder_SetParam(s->handle, AAC_CONCEAL_METHOD, |
228 | s->conceal_method)) != AAC_DEC_OK) { |
229 | av_log(avctx, AV_LOG_ERROR, "Unable to set error concealment method\n"); |
230 | return AVERROR_UNKNOWN; |
231 | } |
232 | |
233 | if (avctx->request_channel_layout > 0 && |
234 | avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) { |
235 | int downmix_channels = -1; |
236 | |
237 | switch (avctx->request_channel_layout) { |
238 | case AV_CH_LAYOUT_STEREO: |
239 | case AV_CH_LAYOUT_STEREO_DOWNMIX: |
240 | downmix_channels = 2; |
241 | break; |
242 | case AV_CH_LAYOUT_MONO: |
243 | downmix_channels = 1; |
244 | break; |
245 | default: |
246 | av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); |
247 | break; |
248 | } |
249 | |
250 | if (downmix_channels != -1) { |
251 | if (aacDecoder_SetParam(s->handle, AAC_PCM_MAX_OUTPUT_CHANNELS, |
252 | downmix_channels) != AAC_DEC_OK) { |
253 | av_log(avctx, AV_LOG_WARNING, "Unable to set output channels in the decoder\n"); |
254 | } else { |
255 | s->anc_buffer = av_malloc(DMX_ANC_BUFFSIZE); |
256 | if (!s->anc_buffer) { |
257 | av_log(avctx, AV_LOG_ERROR, "Unable to allocate ancillary buffer for the decoder\n"); |
258 | return AVERROR(ENOMEM); |
259 | } |
260 | if (aacDecoder_AncDataInit(s->handle, s->anc_buffer, DMX_ANC_BUFFSIZE)) { |
261 | av_log(avctx, AV_LOG_ERROR, "Unable to register downmix ancillary buffer in the decoder\n"); |
262 | return AVERROR_UNKNOWN; |
263 | } |
264 | } |
265 | } |
266 | } |
267 | |
268 | if (s->drc_boost != -1) { |
269 | if (aacDecoder_SetParam(s->handle, AAC_DRC_BOOST_FACTOR, s->drc_boost) != AAC_DEC_OK) { |
270 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC boost factor in the decoder\n"); |
271 | return AVERROR_UNKNOWN; |
272 | } |
273 | } |
274 | |
275 | if (s->drc_cut != -1) { |
276 | if (aacDecoder_SetParam(s->handle, AAC_DRC_ATTENUATION_FACTOR, s->drc_cut) != AAC_DEC_OK) { |
277 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC attenuation factor in the decoder\n"); |
278 | return AVERROR_UNKNOWN; |
279 | } |
280 | } |
281 | |
282 | if (s->drc_level != -1) { |
283 | if (aacDecoder_SetParam(s->handle, AAC_DRC_REFERENCE_LEVEL, s->drc_level) != AAC_DEC_OK) { |
284 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC reference level in the decoder\n"); |
285 | return AVERROR_UNKNOWN; |
286 | } |
287 | } |
288 | |
289 | if (s->drc_heavy != -1) { |
290 | if (aacDecoder_SetParam(s->handle, AAC_DRC_HEAVY_COMPRESSION, s->drc_heavy) != AAC_DEC_OK) { |
291 | av_log(avctx, AV_LOG_ERROR, "Unable to set DRC heavy compression in the decoder\n"); |
292 | return AVERROR_UNKNOWN; |
293 | } |
294 | } |
295 | |
296 | #ifdef AACDECODER_LIB_VL0 |
297 | if (aacDecoder_SetParam(s->handle, AAC_PCM_LIMITER_ENABLE, s->level_limit) != AAC_DEC_OK) { |
298 | av_log(avctx, AV_LOG_ERROR, "Unable to set in signal level limiting in the decoder\n"); |
299 | return AVERROR_UNKNOWN; |
300 | } |
301 | #endif |
302 | |
303 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
304 | |
305 | s->decoder_buffer_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; |
306 | s->decoder_buffer = av_malloc(s->decoder_buffer_size); |
307 | if (!s->decoder_buffer) |
308 | return AVERROR(ENOMEM); |
309 | |
310 | return 0; |
311 | } |
312 | |
313 | static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, |
314 | int *got_frame_ptr, AVPacket *avpkt) |
315 | { |
316 | FDKAACDecContext *s = avctx->priv_data; |
317 | AVFrame *frame = data; |
318 | int ret; |
319 | AAC_DECODER_ERROR err; |
320 | UINT valid = avpkt->size; |
321 | |
322 | err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); |
323 | if (err != AAC_DEC_OK) { |
324 | av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); |
325 | return AVERROR_INVALIDDATA; |
326 | } |
327 | |
328 | err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size, 0); |
329 | if (err == AAC_DEC_NOT_ENOUGH_BITS) { |
330 | ret = avpkt->size - valid; |
331 | goto end; |
332 | } |
333 | if (err != AAC_DEC_OK) { |
334 | av_log(avctx, AV_LOG_ERROR, |
335 | "aacDecoder_DecodeFrame() failed: %x\n", err); |
336 | ret = AVERROR_UNKNOWN; |
337 | goto end; |
338 | } |
339 | |
340 | if ((ret = get_stream_info(avctx)) < 0) |
341 | goto end; |
342 | frame->nb_samples = avctx->frame_size; |
343 | |
344 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
345 | goto end; |
346 | |
347 | memcpy(frame->extended_data[0], s->decoder_buffer, |
348 | avctx->channels * avctx->frame_size * |
349 | av_get_bytes_per_sample(avctx->sample_fmt)); |
350 | |
351 | *got_frame_ptr = 1; |
352 | ret = avpkt->size - valid; |
353 | |
354 | end: |
355 | return ret; |
356 | } |
357 | |
358 | static av_cold void fdk_aac_decode_flush(AVCodecContext *avctx) |
359 | { |
360 | FDKAACDecContext *s = avctx->priv_data; |
361 | AAC_DECODER_ERROR err; |
362 | |
363 | if (!s->handle) |
364 | return; |
365 | |
366 | if ((err = aacDecoder_SetParam(s->handle, |
367 | AAC_TPDEC_CLEAR_BUFFER, 1)) != AAC_DEC_OK) |
368 | av_log(avctx, AV_LOG_WARNING, "failed to clear buffer when flushing\n"); |
369 | } |
370 | |
371 | AVCodec ff_libfdk_aac_decoder = { |
372 | .name = "libfdk_aac", |
373 | .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), |
374 | .type = AVMEDIA_TYPE_AUDIO, |
375 | .id = AV_CODEC_ID_AAC, |
376 | .priv_data_size = sizeof(FDKAACDecContext), |
377 | .init = fdk_aac_decode_init, |
378 | .decode = fdk_aac_decode_frame, |
379 | .close = fdk_aac_decode_close, |
380 | .flush = fdk_aac_decode_flush, |
381 | .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, |
382 | .priv_class = &fdk_aac_dec_class, |
383 | .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | |
384 | FF_CODEC_CAP_INIT_CLEANUP, |
385 | }; |
386 |