1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2000-2017
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;
61 } GF_FAADCtx;
62
faaddec_check_mc_config(GF_FAADCtx * ctx)63 static void faaddec_check_mc_config(GF_FAADCtx *ctx)
64 {
65 u32 i, channel_mask = 0;
66 for (i=0; i<ctx->num_channels; i++) {
67 switch (ctx->info.channel_position[i]) {
68 case FRONT_CHANNEL_CENTER:
69 channel_mask |= GF_AUDIO_CH_FRONT_CENTER;
70 break;
71 case FRONT_CHANNEL_LEFT:
72 channel_mask |= GF_AUDIO_CH_FRONT_LEFT;
73 break;
74 case FRONT_CHANNEL_RIGHT:
75 channel_mask |= GF_AUDIO_CH_FRONT_RIGHT;
76 break;
77 case SIDE_CHANNEL_LEFT:
78 channel_mask |= GF_AUDIO_CH_REAR_SURROUND_LEFT;
79 break;
80 case SIDE_CHANNEL_RIGHT:
81 channel_mask |= GF_AUDIO_CH_REAR_SURROUND_RIGHT;
82 break;
83 case BACK_CHANNEL_LEFT:
84 channel_mask |= GF_AUDIO_CH_SURROUND_LEFT;
85 break;
86 case BACK_CHANNEL_RIGHT:
87 channel_mask |= GF_AUDIO_CH_SURROUND_RIGHT;
88 break;
89 case BACK_CHANNEL_CENTER:
90 channel_mask |= GF_AUDIO_CH_REAR_CENTER;
91 break;
92 case LFE_CHANNEL:
93 channel_mask |= GF_AUDIO_CH_LFE;
94 break;
95 default:
96 break;
97 }
98 }
99 if (ctx->channel_mask != channel_mask) {
100 ctx->channel_mask = channel_mask;
101 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(channel_mask) );
102 }
103 }
104
faaddec_configure_pid(GF_Filter * filter,GF_FilterPid * pid,Bool is_remove)105 static GF_Err faaddec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
106 {
107 const GF_PropertyValue *p;
108 GF_FAADCtx *ctx = gf_filter_get_udta(filter);
109 #ifndef GPAC_DISABLE_AV_PARSERS
110 GF_Err e;
111 GF_M4ADecSpecInfo a_cfg;
112 #endif
113
114 if (is_remove) {
115 if (ctx->opid) gf_filter_pid_remove(ctx->opid);
116 ctx->opid = NULL;
117 ctx->ipid = NULL;
118 return GF_OK;
119 }
120 if (! gf_filter_pid_check_caps(pid))
121 return GF_NOT_SUPPORTED;
122
123 if (!ctx->opid) {
124 ctx->opid = gf_filter_pid_new(filter);
125 }
126 //copy properties at init or reconfig
127 gf_filter_pid_copy_properties(ctx->opid, pid);
128 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
129 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16) );
130 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, NULL );
131 ctx->ipid = pid;
132
133
134 p = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
135 if (p && p->value.data.ptr && p->value.data.size) {
136 u32 ex_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
137 if (ctx->cfg_crc && (ctx->cfg_crc != ex_crc)) {
138 //shoud we flush ?
139 if (ctx->codec) NeAACDecClose(ctx->codec);
140 ctx->codec = NULL;
141 }
142 } else {
143 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Reconfiguring but no DSI set, skipping\n"));
144 return GF_OK;
145 }
146
147 ctx->codec = NeAACDecOpen();
148 if (!ctx->codec) {
149 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing decoder\n"));
150 return GF_IO_ERR;
151 }
152
153 #ifndef GPAC_DISABLE_AV_PARSERS
154 e = gf_m4a_get_config(p->value.data.ptr, p->value.data.size, &a_cfg);
155 if (e) return e;
156 #endif
157 if (NeAACDecInit2(ctx->codec, (unsigned char *)p->value.data.ptr, p->value.data.size, (unsigned long*)&ctx->sample_rate, (u8*)&ctx->num_channels) < 0)
158 {
159 #ifndef GPAC_DISABLE_AV_PARSERS
160 s8 res;
161 u8 *dsi, *s_base_object_type;
162 u32 dsi_len;
163 switch (a_cfg.base_object_type) {
164 case GF_M4A_AAC_MAIN:
165 s_base_object_type = gf_stringizer(GF_M4A_AAC_MAIN);
166 goto base_object_type_error;
167 case GF_M4A_AAC_LC:
168 s_base_object_type = gf_stringizer(GF_M4A_AAC_LC);
169 goto base_object_type_error;
170 case GF_M4A_AAC_SSR:
171 s_base_object_type = gf_stringizer(GF_M4A_AAC_SSR);
172 goto base_object_type_error;
173 case GF_M4A_AAC_LTP:
174 s_base_object_type = gf_stringizer(GF_M4A_AAC_LTP);
175 goto base_object_type_error;
176 case GF_M4A_AAC_SBR:
177 s_base_object_type = gf_stringizer(GF_M4A_AAC_SBR);
178 goto base_object_type_error;
179 case GF_M4A_AAC_PS:
180 s_base_object_type = gf_stringizer(GF_M4A_AAC_PS);
181 base_object_type_error: /*error case*/
182 GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error: unsupported %s format for stream - defaulting to AAC LC\n", s_base_object_type));
183 default:
184 break;
185 }
186 a_cfg.base_object_type = GF_M4A_AAC_LC;
187 a_cfg.has_sbr = GF_FALSE;
188 a_cfg.nb_chan = a_cfg.nb_chan > 2 ? 1 : a_cfg.nb_chan;
189
190 gf_m4a_write_config(&a_cfg, &dsi, &dsi_len);
191 res = NeAACDecInit2(ctx->codec, (unsigned char *) dsi, dsi_len, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels);
192 gf_free(dsi);
193 if (res < 0)
194 #endif
195 {
196 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error when initializing AAC decoder for stream\n"));
197 return GF_NOT_SUPPORTED;
198 }
199 }
200
201 #ifndef GPAC_DISABLE_AV_PARSERS
202 ctx->is_sbr = a_cfg.has_sbr;
203 #endif
204 ctx->num_samples = 1024;
205 ctx->signal_mc = ctx->num_channels>2 ? GF_TRUE : GF_FALSE;
206
207 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
208 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, &PROP_UINT(ctx->num_samples) );
209 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
210
211 #if 0
212 if (!strcmp(FAAD2_VERSION, "unknown")) {
213 if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-" FAAD2_VERSION "-SBR");
214 else gf_filter_set_name(filter, "dec_faad:FAAD2-" FAAD2_VERSION);
215 } else
216 #endif
217 {
218 if (ctx->is_sbr) gf_filter_set_name(filter, "dec_faad:FAAD2-SBR");
219 else gf_filter_set_name(filter, "dec_faad:FAAD2");
220 }
221 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
222 return GF_OK;
223 }
224
faaddec_get_channel_pos(GF_FAADCtx * ffd,u32 ch_cfg)225 static s8 faaddec_get_channel_pos(GF_FAADCtx *ffd, u32 ch_cfg)
226 {
227 u32 i;
228 for (i=0; i<ffd->info.channels; i++) {
229 switch (ffd->info.channel_position[i]) {
230 case FRONT_CHANNEL_CENTER:
231 if (ch_cfg==GF_AUDIO_CH_FRONT_CENTER) return i;
232 break;
233 case FRONT_CHANNEL_LEFT:
234 if (ch_cfg==GF_AUDIO_CH_FRONT_LEFT) return i;
235 break;
236 case FRONT_CHANNEL_RIGHT:
237 if (ch_cfg==GF_AUDIO_CH_FRONT_RIGHT) return i;
238 break;
239 case SIDE_CHANNEL_LEFT:
240 if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_LEFT) return i;
241 break;
242 case SIDE_CHANNEL_RIGHT:
243 if (ch_cfg==GF_AUDIO_CH_REAR_SURROUND_RIGHT) return i;
244 break;
245 case BACK_CHANNEL_LEFT:
246 if (ch_cfg==GF_AUDIO_CH_SURROUND_LEFT) return i;
247 break;
248 case BACK_CHANNEL_RIGHT:
249 if (ch_cfg==GF_AUDIO_CH_SURROUND_RIGHT) return i;
250 break;
251 case BACK_CHANNEL_CENTER:
252 if (ch_cfg==GF_AUDIO_CH_REAR_CENTER) return i;
253 break;
254 case LFE_CHANNEL:
255 if (ch_cfg==GF_AUDIO_CH_LFE) return i;
256 break;
257 }
258 }
259 return -1;
260 }
261
faaddec_process(GF_Filter * filter)262 static GF_Err faaddec_process(GF_Filter *filter)
263 {
264 GF_FAADCtx *ctx = gf_filter_get_udta(filter);
265 void *buffer;
266 u8 *output;
267 u32 i, j;
268 Bool is_eos = GF_FALSE;
269 GF_FilterPacket *dst_pck;
270 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
271
272 if (!pck) {
273 is_eos = gf_filter_pid_is_eos(ctx->ipid);
274 if (!is_eos) return GF_OK;
275 }
276
277 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Decoding AU\n"));
278 if (!pck) {
279 buffer = NeAACDecDecode(ctx->codec, &ctx->info, NULL, 0);
280 } else {
281 Bool start, end;
282 u32 size;
283 const char *data = gf_filter_pck_get_data(pck, &size);
284 buffer = NeAACDecDecode(ctx->codec, &ctx->info, (char *) data, size);
285
286 gf_filter_pck_get_framing(pck, &start, &end);
287 assert(start && end);
288 }
289
290 if (ctx->info.error>0) {
291 GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FAAD] Error decoding AU %s\n", NeAACDecGetErrorMessage(ctx->info.error) ));
292 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
293 return GF_NON_COMPLIANT_BITSTREAM;
294 }
295 if (!ctx->info.samples || !buffer || !ctx->info.bytesconsumed) {
296 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] empty/non complete AU\n"));
297 if (is_eos) gf_filter_pid_set_eos(ctx->opid);
298 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
299 return GF_OK;
300 }
301 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] AU decoded\n"));
302
303 /*FAAD froces us to decode a frame to get channel cfg*/
304 if (ctx->signal_mc) {
305 s32 ch, idx;
306 ctx->signal_mc = GF_FALSE;
307 idx = 0;
308 /*NOW WATCH OUT!! FAAD may very well decide to output more channels than indicated!!!*/
309 ctx->num_channels = ctx->info.channels;
310
311 /*get cfg*/
312 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_LEFT);
313 if (ch>=0) {
314 ctx->ch_reorder[idx] = ch;
315 idx++;
316 }
317 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_RIGHT);
318 if (ch>=0) {
319 ctx->ch_reorder[idx] = ch;
320 idx++;
321 }
322 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_FRONT_CENTER);
323 if (ch>=0) {
324 ctx->ch_reorder[idx] = ch;
325 idx++;
326 }
327 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_LFE);
328 if (ch>=0) {
329 ctx->ch_reorder[idx] = ch;
330 idx++;
331 }
332 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_LEFT);
333 if (ch>=0) {
334 ctx->ch_reorder[idx] = ch;
335 idx++;
336 }
337 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_SURROUND_RIGHT);
338 if (ch>=0) {
339 ctx->ch_reorder[idx] = ch;
340 idx++;
341 }
342 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_CENTER);
343 if (ch>=0) {
344 ctx->ch_reorder[idx] = ch;
345 idx++;
346 }
347 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_LEFT);
348 if (ch>=0) {
349 ctx->ch_reorder[idx] = ch;
350 idx++;
351 }
352 ch = faaddec_get_channel_pos(ctx, GF_AUDIO_CH_REAR_SURROUND_RIGHT);
353 if (ch>=0) {
354 ctx->ch_reorder[idx] = ch;
355 //last one, no need to increment idx++;
356 }
357 faaddec_check_mc_config(ctx);
358 }
359
360 dst_pck = gf_filter_pck_new_alloc(ctx->opid, (u32) (sizeof(short) * ctx->info.samples), &output);
361 if (!dst_pck) {
362 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
363 return GF_OUT_OF_MEM;
364 }
365 if (pck) {
366 ctx->last_cts = gf_filter_pck_get_cts(pck);
367 ctx->timescale = gf_filter_pck_get_timescale(pck);
368 gf_filter_pck_merge_properties(pck, dst_pck);
369 }
370 gf_filter_pck_set_cts(dst_pck, ctx->last_cts);
371 if (ctx->timescale != ctx->sample_rate) {
372 u64 dur =ctx->info.samples * ctx->timescale;
373 dur /= ctx->sample_rate;
374 gf_filter_pck_set_duration(dst_pck, (u32) dur);
375 ctx->last_cts += dur;
376 } else {
377 gf_filter_pck_set_duration(dst_pck, (u32) ctx->info.samples);
378 ctx->last_cts += ctx->info.samples;
379 }
380 /*we assume left/right order*/
381 if (ctx->num_channels<=2) {
382 memcpy(output, buffer, sizeof(short)* ctx->info.samples);
383 } else {
384 unsigned short *conv_in, *conv_out;
385 conv_in = (unsigned short *) buffer;
386 conv_out = (unsigned short *) output;
387 for (i=0; i<ctx->info.samples; i+=ctx->info.channels) {
388 for (j=0; j<ctx->info.channels; j++) {
389 conv_out[i + j] = conv_in[i + ctx->ch_reorder[j]];
390 }
391 }
392 }
393 gf_filter_pck_send(dst_pck);
394 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
395 return GF_OK;
396 }
397
398 static const GF_FilterCapability FAADCaps[] =
399 {
400 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
401 CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
402 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG4),
403 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_MP),
404 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_LCP),
405 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AAC_MPEG2_SSRP),
406 CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
407 CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
408 };
409
410 GF_FilterRegister FAADRegister = {
411 .name = "faad",
412 GF_FS_SET_DESCRIPTION("FAAD decoder")
413 GF_FS_SET_HELP("This filter decodes AAC streams through faad library.")
414 .private_size = sizeof(GF_FAADCtx),
415 .priority = 1,
416 SETCAPS(FAADCaps),
417 .configure_pid = faaddec_configure_pid,
418 .process = faaddec_process,
419 };
420
421 #endif
422
faad_register(GF_FilterSession * session)423 const GF_FilterRegister *faad_register(GF_FilterSession *session)
424 {
425 #ifdef GPAC_HAS_FAAD
426 return &FAADRegister;
427 #else
428 return NULL;
429 #endif
430 }
431