Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / AAC FAAD2 decoder filter
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/filters.h>
27 : #include <gpac/constants.h>
28 :
29 : #ifdef GPAC_HAS_FAAD
30 :
31 : #ifdef __GNUC__
32 : #pragma GCC diagnostic ignored "-Wunknown-pragmas"
33 : #endif
34 :
35 : #if !defined(__GNUC__)
36 : # if defined(_WIN32_WCE) || defined (WIN32)
37 : # pragma comment(lib, "libfaad")
38 : # endif
39 : #endif
40 :
41 : #include <neaacdec.h>
42 : #include <gpac/constants.h>
43 : #include <gpac/avparse.h>
44 :
45 :
46 : typedef struct
47 : {
48 : NeAACDecHandle codec;
49 : NeAACDecFrameInfo info; u32 sample_rate, timescale, num_samples;
50 : u8 num_channels;
51 :
52 : GF_FilterPid *ipid, *opid;
53 : u32 cfg_crc;
54 :
55 : Bool signal_mc;
56 : Bool is_sbr;
57 :
58 : u32 channel_mask;
59 : char ch_reorder[16];
60 : u64 last_cts, first_priming_cts_plus_one;
61 : u32 ts_offset;
62 : } GF_FAADCtx;
63 :
64 2 : static void faaddec_check_mc_config(GF_FAADCtx *ctx)
65 : {
66 : u32 i, channel_mask = 0;
67 14 : for (i=0; i<ctx->num_channels; i++) {
68 12 : switch (ctx->info.channel_position[i]) {
69 2 : case FRONT_CHANNEL_CENTER:
70 2 : channel_mask |= GF_AUDIO_CH_FRONT_CENTER;
71 2 : break;
72 2 : case FRONT_CHANNEL_LEFT:
73 2 : channel_mask |= GF_AUDIO_CH_FRONT_LEFT;
74 2 : break;
75 2 : case FRONT_CHANNEL_RIGHT:
76 2 : channel_mask |= GF_AUDIO_CH_FRONT_RIGHT;
77 2 : break;
78 0 : case SIDE_CHANNEL_LEFT:
79 0 : channel_mask |= GF_AUDIO_CH_REAR_SURROUND_LEFT;
80 0 : break;
81 0 : case SIDE_CHANNEL_RIGHT:
82 0 : channel_mask |= GF_AUDIO_CH_REAR_SURROUND_RIGHT;
83 0 : break;
84 2 : case BACK_CHANNEL_LEFT:
85 2 : channel_mask |= GF_AUDIO_CH_SURROUND_LEFT;
86 2 : break;
87 2 : case BACK_CHANNEL_RIGHT:
88 2 : channel_mask |= GF_AUDIO_CH_SURROUND_RIGHT;
89 2 : break;
90 0 : case BACK_CHANNEL_CENTER:
91 0 : channel_mask |= GF_AUDIO_CH_REAR_CENTER;
92 0 : break;
93 2 : case LFE_CHANNEL:
94 2 : channel_mask |= GF_AUDIO_CH_LFE;
95 2 : break;
96 : default:
97 : break;
98 : }
99 : }
100 2 : if (ctx->channel_mask != channel_mask) {
101 2 : ctx->channel_mask = channel_mask;
102 2 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(channel_mask) );
103 : }
104 2 : }
105 :
106 4 : static GF_Err faaddec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
107 : {
108 : const GF_PropertyValue *p;
109 4 : GF_FAADCtx *ctx = gf_filter_get_udta(filter);
110 : #ifndef GPAC_DISABLE_AV_PARSERS
111 : GF_Err e;
112 : GF_M4ADecSpecInfo a_cfg;
113 : #endif
114 :
115 4 : if (is_remove) {
116 0 : if (ctx->opid) {
117 0 : gf_filter_pid_remove(ctx->opid);
118 0 : ctx->opid = NULL;
119 : }
120 0 : ctx->ipid = NULL;
121 0 : return GF_OK;
122 : }
123 4 : if (! gf_filter_pid_check_caps(pid))
124 : return GF_NOT_SUPPORTED;
125 :
126 4 : if (!ctx->opid) {
127 4 : ctx->opid = gf_filter_pid_new(filter);
128 : }
129 : //copy properties at init or reconfig
130 4 : gf_filter_pid_copy_properties(ctx->opid, pid);
131 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
132 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16) );
133 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL );
134 4 : ctx->ipid = pid;
135 :
136 :
137 4 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_NO_PRIMING);
138 : //force re-priming
139 4 : if (p && !p->value.boolean) {
140 0 : ctx->cfg_crc = 0;
141 : }
142 :
143 4 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
144 4 : if (p && p->value.data.ptr && p->value.data.size) {
145 4 : u32 ex_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
146 4 : if (ctx->cfg_crc == ex_crc)
147 : return GF_OK;
148 : //no need to flush
149 4 : if (ctx->codec) NeAACDecClose(ctx->codec);
150 4 : ctx->codec = NULL;
151 4 : ctx->cfg_crc = ex_crc;
152 : } else {
153 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Reconfiguring but no DSI set, skipping\n"));
154 : return GF_OK;
155 : }
156 :
157 4 : ctx->codec = NeAACDecOpen();
158 4 : if (!ctx->codec) {
159 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing decoder\n"));
160 : return GF_IO_ERR;
161 : }
162 :
163 4 : ctx->ts_offset = 0;
164 4 : ctx->first_priming_cts_plus_one = 0;
165 :
166 : #ifndef GPAC_DISABLE_AV_PARSERS
167 4 : e = gf_m4a_get_config(p->value.data.ptr, p->value.data.size, &a_cfg);
168 4 : if (e) return e;
169 : #endif
170 4 : if (NeAACDecInit2(ctx->codec, (unsigned char *)p->value.data.ptr, p->value.data.size, (unsigned long*)&ctx->sample_rate, (u8*)&ctx->num_channels) < 0)
171 : {
172 : #ifndef GPAC_DISABLE_AV_PARSERS
173 : s8 res;
174 : u8 *dsi, *s_base_object_type;
175 : u32 dsi_len;
176 0 : switch (a_cfg.base_object_type) {
177 : case GF_M4A_AAC_MAIN:
178 : s_base_object_type = gf_stringizer(GF_M4A_AAC_MAIN);
179 : goto base_object_type_error;
180 0 : case GF_M4A_AAC_LC:
181 : s_base_object_type = gf_stringizer(GF_M4A_AAC_LC);
182 0 : goto base_object_type_error;
183 0 : case GF_M4A_AAC_SSR:
184 : s_base_object_type = gf_stringizer(GF_M4A_AAC_SSR);
185 0 : goto base_object_type_error;
186 0 : case GF_M4A_AAC_LTP:
187 : s_base_object_type = gf_stringizer(GF_M4A_AAC_LTP);
188 0 : goto base_object_type_error;
189 0 : case GF_M4A_AAC_SBR:
190 : s_base_object_type = gf_stringizer(GF_M4A_AAC_SBR);
191 0 : goto base_object_type_error;
192 0 : case GF_M4A_AAC_PS:
193 : s_base_object_type = gf_stringizer(GF_M4A_AAC_PS);
194 0 : base_object_type_error: /*error case*/
195 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream - defaulting to AAC LC\n", s_base_object_type));
196 : default:
197 : break;
198 : }
199 0 : a_cfg.base_object_type = GF_M4A_AAC_LC;
200 0 : a_cfg.has_sbr = GF_FALSE;
201 0 : a_cfg.nb_chan = a_cfg.nb_chan > 2 ? 1 : a_cfg.nb_chan;
202 :
203 0 : gf_m4a_write_config(&a_cfg, &dsi, &dsi_len);
204 0 : res = NeAACDecInit2(ctx->codec, (unsigned char *) dsi, dsi_len, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels);
205 0 : gf_free(dsi);
206 0 : if (res < 0)
207 : #endif
208 : {
209 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error when initializing AAC decoder for stream\n"));
210 0 : return GF_NOT_SUPPORTED;
211 : }
212 : }
213 :
214 : #ifndef GPAC_DISABLE_AV_PARSERS
215 4 : ctx->is_sbr = a_cfg.has_sbr;
216 : #endif
217 4 : ctx->num_samples = 1024;
218 4 : ctx->signal_mc = ctx->num_channels>2 ? GF_TRUE : GF_FALSE;
219 :
220 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
221 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, &PROP_UINT(ctx->num_samples) );
222 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
223 :
224 : #if 0
225 : if (!strcmp(FAAD2_VERSION, "unknown")) {
226 : if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-" FAAD2_VERSION "-SBR");
227 : else gf_filter_set_name(filter, "dec_faad:FAAD2-" FAAD2_VERSION);
228 : } else
229 : #endif
230 : {
231 4 : if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-SBR");
232 4 : else gf_filter_set_name(filter, "dec_faad:FAAD2");
233 : }
234 4 : gf_filter_pid_set_framing_mode(pid, GF_TRUE);
235 :
236 :
237 4 : return GF_OK;
238 : }
239 :
240 18 : static s8 faaddec_get_channel_pos(GF_FAADCtx *ffd, u32 ch_cfg)
241 : {
242 : u32 i;
243 84 : for (i=0; i<ffd->info.channels; i++) {
244 78 : switch (ffd->info.channel_position[i]) {
245 18 : case FRONT_CHANNEL_CENTER:
246 18 : if (ch_cfg==GF_AUDIO_CH_FRONT_CENTER) return i;
247 : break;
248 16 : case FRONT_CHANNEL_LEFT:
249 16 : if (ch_cfg==GF_AUDIO_CH_FRONT_LEFT) return i;
250 : break;
251 14 : case FRONT_CHANNEL_RIGHT:
252 14 : if (ch_cfg==GF_AUDIO_CH_FRONT_RIGHT) return i;
253 : break;
254 0 : case SIDE_CHANNEL_LEFT:
255 0 : if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_LEFT) return i;
256 : break;
257 0 : case SIDE_CHANNEL_RIGHT:
258 0 : if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_RIGHT) return i;
259 : break;
260 12 : case BACK_CHANNEL_LEFT:
261 12 : if (ch_cfg==GF_AUDIO_CH_SURROUND_LEFT) return i;
262 : break;
263 10 : case BACK_CHANNEL_RIGHT:
264 10 : if (ch_cfg==GF_AUDIO_CH_SURROUND_RIGHT) return i;
265 : break;
266 0 : case BACK_CHANNEL_CENTER:
267 0 : if (ch_cfg==GF_AUDIO_CH_REAR_CENTER) return i;
268 : break;
269 8 : case LFE_CHANNEL:
270 8 : if (ch_cfg==GF_AUDIO_CH_LFE) return i;
271 : break;
272 : }
273 : }
274 : return -1;
275 : }
276 :
277 1122 : static GF_Err faaddec_process(GF_Filter *filter)
278 : {
279 1122 : GF_FAADCtx *ctx = gf_filter_get_udta(filter);
280 : void *buffer;
281 : u8 *output;
282 : u32 i, j;
283 : Bool is_eos = GF_FALSE;
284 : GF_FilterPacket *dst_pck;
285 1122 : GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
286 :
287 1122 : if (!pck) {
288 586 : is_eos = gf_filter_pid_is_eos(ctx->ipid);
289 586 : if (!is_eos) return GF_OK;
290 : }
291 :
292 538 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Decoding AU\n"));
293 538 : if (!pck) {
294 2 : buffer = NeAACDecDecode(ctx->codec, &ctx->info, NULL, 0);
295 : } else {
296 : Bool start, end;
297 : u32 size;
298 536 : const char *data = gf_filter_pck_get_data(pck, &size);
299 536 : buffer = NeAACDecDecode(ctx->codec, &ctx->info, (char *) data, size);
300 :
301 536 : gf_filter_pck_get_framing(pck, &start, &end);
302 : assert(start && end);
303 : }
304 :
305 538 : if (ctx->info.error>0) {
306 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error decoding AU %s\n", NeAACDecGetErrorMessage(ctx->info.error) ));
307 0 : if (pck) gf_filter_pid_drop_packet(ctx->ipid);
308 : return GF_NON_COMPLIANT_BITSTREAM;
309 : }
310 538 : if (!ctx->info.samples || !buffer || !ctx->info.bytesconsumed) {
311 6 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] empty/non complete AU\n"));
312 6 : if (is_eos) gf_filter_pid_set_eos(ctx->opid);
313 6 : if (pck) {
314 4 : if (!ctx->first_priming_cts_plus_one) {
315 4 : ctx->first_priming_cts_plus_one = gf_filter_pck_get_cts(pck) + 1;
316 :
317 : }
318 4 : gf_filter_pid_drop_packet(ctx->ipid);
319 : }
320 : return GF_OK;
321 : }
322 532 : GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] AU decoded\n"));
323 :
324 : /*FAAD froces us to decode a frame to get channel cfg*/
325 532 : if (ctx->signal_mc) {
326 : s32 ch, idx;
327 2 : ctx->signal_mc = GF_FALSE;
328 : idx = 0;
329 : /*NOW WATCH OUT!! FAAD may very well decide to output more channels than indicated!!!*/
330 2 : ctx->num_channels = ctx->info.channels;
331 :
332 : /*get cfg*/
333 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_LEFT);
334 2 : if (ch>=0) {
335 2 : ctx->ch_reorder[idx] = ch;
336 : idx++;
337 : }
338 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_RIGHT);
339 2 : if (ch>=0) {
340 2 : ctx->ch_reorder[idx] = ch;
341 2 : idx++;
342 : }
343 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_CENTER);
344 2 : if (ch>=0) {
345 2 : ctx->ch_reorder[idx] = ch;
346 2 : idx++;
347 : }
348 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_LFE);
349 2 : if (ch>=0) {
350 2 : ctx->ch_reorder[idx] = ch;
351 2 : idx++;
352 : }
353 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_LEFT);
354 2 : if (ch>=0) {
355 2 : ctx->ch_reorder[idx] = ch;
356 2 : idx++;
357 : }
358 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_RIGHT);
359 2 : if (ch>=0) {
360 2 : ctx->ch_reorder[idx] = ch;
361 2 : idx++;
362 : }
363 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_CENTER);
364 2 : if (ch>=0) {
365 0 : ctx->ch_reorder[idx] = ch;
366 0 : idx++;
367 : }
368 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_LEFT);
369 2 : if (ch>=0) {
370 0 : ctx->ch_reorder[idx] = ch;
371 0 : idx++;
372 : }
373 2 : ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_RIGHT);
374 2 : if (ch>=0) {
375 0 : ctx->ch_reorder[idx] = ch;
376 : //last one, no need to increment idx++;
377 : }
378 2 : faaddec_check_mc_config(ctx);
379 : }
380 :
381 532 : if (ctx->timescale && pck && gf_filter_pid_eos_received(ctx->ipid)) {
382 24 : u64 odur = gf_filter_pck_get_duration(pck);
383 24 : if (ctx->timescale != ctx->sample_rate) {
384 7 : odur *= ctx->sample_rate;
385 7 : odur /= ctx->timescale;
386 : }
387 24 : if (odur * ctx->info.channels < ctx->info.samples) {
388 0 : ctx->info.samples = (unsigned long) (odur * ctx->info.channels);
389 : }
390 : }
391 :
392 532 : dst_pck = gf_filter_pck_new_alloc(ctx->opid, (u32) (sizeof(short) * ctx->info.samples), &output);
393 532 : if (!dst_pck) {
394 0 : if (pck) gf_filter_pid_drop_packet(ctx->ipid);
395 : return GF_OUT_OF_MEM;
396 : }
397 532 : if (pck) {
398 532 : ctx->last_cts = gf_filter_pck_get_cts(pck);
399 532 : if (ctx->first_priming_cts_plus_one && !ctx->ts_offset) {
400 4 : if (ctx->last_cts + 1 >= ctx->first_priming_cts_plus_one)
401 4 : ctx->ts_offset = (u32) (ctx->last_cts - (ctx->first_priming_cts_plus_one-1));
402 : else
403 : //neg speed
404 0 : ctx->ts_offset = (u32) ((ctx->first_priming_cts_plus_one-1) - ctx->last_cts);
405 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DELAY, NULL);
406 : }
407 532 : ctx->last_cts -= ctx->ts_offset;
408 532 : ctx->timescale = gf_filter_pck_get_timescale(pck);
409 532 : gf_filter_pck_merge_properties(pck, dst_pck);
410 : }
411 532 : gf_filter_pck_set_cts(dst_pck, ctx->last_cts);
412 532 : if (ctx->timescale != ctx->sample_rate) {
413 261 : u64 dur =ctx->info.samples * ctx->timescale;
414 261 : dur /= ctx->sample_rate;
415 261 : gf_filter_pck_set_duration(dst_pck, (u32) dur);
416 261 : ctx->last_cts += dur;
417 : } else {
418 271 : gf_filter_pck_set_duration(dst_pck, (u32) ctx->info.samples);
419 271 : ctx->last_cts += ctx->info.samples;
420 : }
421 : /*we assume left/right order*/
422 532 : if (ctx->num_channels<=2) {
423 271 : memcpy(output, buffer, sizeof(short)* ctx->info.samples);
424 : } else {
425 : unsigned short *conv_in, *conv_out;
426 : conv_in = (unsigned short *) buffer;
427 261 : conv_out = (unsigned short *) output;
428 534789 : for (i=0; i<ctx->info.samples; i+=ctx->info.channels) {
429 3207168 : for (j=0; j<ctx->info.channels; j++) {
430 3207168 : conv_out[i + j] = conv_in[i + ctx->ch_reorder[j]];
431 : }
432 : }
433 : }
434 532 : gf_filter_pck_send(dst_pck);
435 532 : if (pck) gf_filter_pid_drop_packet(ctx->ipid);
436 : return GF_OK;
437 : }
438 :
439 4 : static void faaddec_finalize(GF_Filter *filter)
440 : {
441 4 : GF_FAADCtx *ctx = gf_filter_get_udta(filter);
442 4 : if (ctx->codec) NeAACDecClose(ctx->codec);
443 4 : }
444 : static const GF_FilterCapability FAADCaps[] =
445 : {
446 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
447 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
448 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
449 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
450 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
451 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
452 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
453 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
454 : };
455 :
456 : GF_FilterRegister FAADRegister = {
457 : .name = "faad",
458 : GF_FS_SET_DESCRIPTION("FAAD decoder")
459 : GF_FS_SET_HELP("This filter decodes AAC streams through faad library.")
460 : .private_size = sizeof(GF_FAADCtx),
461 : .priority = 200, //lower priority than ffdec, as faad support for multichannel is not really good
462 : SETCAPS(FAADCaps),
463 : .configure_pid = faaddec_configure_pid,
464 : .finalize = faaddec_finalize,
465 : .process = faaddec_process,
466 : };
467 :
468 : #endif
469 :
470 2877 : const GF_FilterRegister *faad_register(GF_FilterSession *session)
471 : {
472 : #ifdef GPAC_HAS_FAAD
473 2877 : return &FAADRegister;
474 : #else
475 : return NULL;
476 : #endif
477 : }
|