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 / AC3 liba52 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_LIBA52
30
31 #if !defined(__GNUC__)
32 # if defined(_WIN32_WCE) || defined (WIN32)
33 # pragma comment(lib, "liba52")
34 # endif
35 #endif
36
37
38 #ifndef uint32_t
39 #define uint32_t u32
40 #endif
41 #ifndef uint8_t
42 #define uint8_t u8
43 #endif
44
45 #include <a52dec/mm_accel.h>
46 #include <a52dec/a52.h>
47
48 #define AC3_FRAME_SIZE 1536
49
50 typedef struct
51 {
52 GF_FilterPid *ipid, *opid;
53
54 a52_state_t *codec;
55 sample_t* samples;
56
57 u32 sample_rate, flags, bit_rate;
58 u8 num_channels;
59 u32 channel_mask;
60 u64 last_cts;
61 u32 timescale;
62 } GF_A52DecCtx;
63
64
a52dec_configure_pid(GF_Filter * filter,GF_FilterPid * pid,Bool is_remove)65 static GF_Err a52dec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
66 {
67 GF_A52DecCtx *ctx = gf_filter_get_udta(filter);
68
69 if (is_remove) {
70 if (ctx->opid) gf_filter_pid_remove(ctx->opid);
71 ctx->opid = NULL;
72 ctx->ipid = NULL;
73 return GF_OK;
74 }
75 if (! gf_filter_pid_check_caps(pid))
76 return GF_NOT_SUPPORTED;
77
78 ctx->ipid = pid;
79 gf_filter_pid_set_framing_mode(ctx->ipid, GF_TRUE);
80 if (!ctx->opid) {
81 u32 flags = MM_ACCEL_DJBFFT;
82 #if !defined (GPAC_CONFIG_IOS) && !defined (GPAC_CONFIG_ANDROID)
83 flags |= MM_ACCEL_X86_MMX | MM_ACCEL_X86_3DNOW | MM_ACCEL_X86_MMXEXT;
84 #endif
85 ctx->codec = a52_init(flags);
86 if (!ctx->codec) {
87 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[A52] Error initializing decoder\n"));
88 return GF_IO_ERR;
89 }
90
91 ctx->samples = a52_samples(ctx->codec);
92 if (!ctx->samples) {
93 a52_free(ctx->codec);
94 GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[A52] Error initializing decoder\n"));
95 return GF_IO_ERR;
96 }
97
98 ctx->opid = gf_filter_pid_new(filter);
99 }
100 //copy properties at init or reconfig
101 gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
102 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
103 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16) );
104 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, &PROP_UINT(AC3_FRAME_SIZE) );
105 return GF_OK;
106 }
107
a52dec_finalize(GF_Filter * filter)108 static void a52dec_finalize(GF_Filter *filter)
109 {
110 GF_A52DecCtx *ctx = gf_filter_get_udta(filter);
111 if (ctx->codec) a52_free(ctx->codec);
112 }
113
114
a52dec_check_mc_config(GF_A52DecCtx * ctx)115 static void a52dec_check_mc_config(GF_A52DecCtx *ctx)
116 {
117 u32 channel_mask = 0;
118
119 switch (ctx->flags & A52_CHANNEL_MASK) {
120 case A52_CHANNEL1:
121 case A52_CHANNEL2:
122 case A52_MONO:
123 channel_mask = GF_AUDIO_CH_FRONT_CENTER;
124 break;
125 case A52_CHANNEL:
126 case A52_STEREO:
127 channel_mask = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;
128 break;
129 case A52_DOLBY:
130 break;
131 case A52_3F:
132 channel_mask = GF_AUDIO_CH_FRONT_CENTER | GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;
133 break;
134 case A52_2F1R:
135 channel_mask = GF_AUDIO_CH_REAR_CENTER | GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;
136 break;
137 case A52_3F1R:
138 channel_mask = GF_AUDIO_CH_FRONT_CENTER | GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_REAR_CENTER;
139 break;
140 case A52_2F2R:
141 channel_mask = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_SURROUND_LEFT | GF_AUDIO_CH_SURROUND_RIGHT;
142 break;
143 case A52_3F2R:
144 channel_mask = GF_AUDIO_CH_FRONT_CENTER | GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_SURROUND_LEFT | GF_AUDIO_CH_SURROUND_RIGHT;
145 break;
146 }
147 if (ctx->flags & A52_LFE)
148 channel_mask |= GF_AUDIO_CH_LFE;
149
150 if (ctx->channel_mask != channel_mask) {
151 ctx->channel_mask = channel_mask;
152 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(channel_mask) );
153 }
154 }
155
156
157 /**** the following two functions comes from a52dec */
blah(s32 i)158 static GFINLINE s32 blah (s32 i)
159 {
160 if (i > 0x43c07fff)
161 return 32767;
162 else if (i < 0x43bf8000)
163 return -32768;
164 return i - 0x43c00000;
165 }
166
float_to_int(float * _f,s16 * samps,int nchannels)167 static GFINLINE void float_to_int (float * _f, s16 *samps, int nchannels)
168 {
169 int i, j, c;
170 s32 * f = (s32 *) _f; // XXX assumes IEEE float format
171
172 j = 0;
173 nchannels *= 256;
174 for (i = 0; i < 256; i++) {
175 for (c = 0; c < nchannels; c += 256)
176 samps[j++] = blah (f[i + c]);
177 }
178 }
179
180 /**** end */
181
182 static const int ac3_channels[8] = {
183 2, 1, 2, 3, 3, 4, 4, 5
184 };
185
a52dec_process(GF_Filter * filter)186 static GF_Err a52dec_process(GF_Filter *filter)
187 {
188 short *out_samples;
189 int i, len, bit_rate;
190 u32 size;
191 const char *data;
192 u8 *buffer;
193 u32 sample_rate, flags;
194 u8 num_channels;
195 sample_t level;
196 GF_A52DecCtx *ctx = gf_filter_get_udta(filter);
197 GF_FilterPacket *dst_pck;
198 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
199
200 if (!pck) {
201 if ( gf_filter_pid_is_eos(ctx->ipid)) {
202 gf_filter_pid_set_eos(ctx->opid);
203 return GF_EOS;
204 }
205 return GF_OK;
206 }
207 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[A52] Decoding AU\n"));
208
209 data = gf_filter_pck_get_data(pck, &size);
210 len = a52_syncinfo((u8 *) data, &flags, &sample_rate, &bit_rate);
211 if (!len) return GF_NON_COMPLIANT_BITSTREAM;
212
213 num_channels = ac3_channels[flags & 7];
214 if (flags & A52_LFE) num_channels++;
215 flags |= A52_ADJUST_LEVEL;
216 if ((sample_rate != ctx->sample_rate) || (num_channels != ctx->num_channels) || (ctx->flags != flags) ) {
217 ctx->num_channels = num_channels;
218 ctx->sample_rate = sample_rate;
219 ctx->flags = flags;
220
221 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
222 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
223 a52dec_check_mc_config(ctx);
224 }
225 if (ctx->bit_rate != bit_rate) {
226 ctx->bit_rate = bit_rate;
227 gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, &PROP_UINT(ctx->bit_rate) );
228 }
229 level = 1;
230 if ( a52_frame(ctx->codec, (u8 *) data, &ctx->flags, &level, 384)) {
231 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[A52] Error decoding AU\n" ));
232 if (pck) gf_filter_pid_drop_packet(ctx->ipid);
233 return GF_NON_COMPLIANT_BITSTREAM;
234 }
235 dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->num_channels * sizeof(short) * AC3_FRAME_SIZE, &buffer);
236
237 if (pck) {
238 ctx->last_cts = gf_filter_pck_get_cts(pck);
239 ctx->timescale = gf_filter_pck_get_timescale(pck);
240 gf_filter_pck_merge_properties(pck, dst_pck);
241
242 gf_filter_pid_drop_packet(ctx->ipid);
243 }
244 gf_filter_pck_set_cts(dst_pck, ctx->last_cts);
245 if (ctx->timescale != ctx->sample_rate) {
246 u64 dur = AC3_FRAME_SIZE * ctx->timescale;
247 dur /= ctx->sample_rate;
248 gf_filter_pck_set_duration(dst_pck, (u32) dur);
249 ctx->last_cts += dur;
250 } else {
251 gf_filter_pck_set_duration(dst_pck, AC3_FRAME_SIZE);
252 ctx->last_cts += AC3_FRAME_SIZE;
253 }
254
255 out_samples = (short*)buffer;
256 for (i=0; i<6; i++) {
257 if (a52_block(ctx->codec))
258 return GF_NON_COMPLIANT_BITSTREAM;
259
260 float_to_int(ctx->samples, out_samples + i * 256 * ctx->num_channels, ctx->num_channels);
261 }
262 gf_filter_pck_send(dst_pck);
263
264 return GF_OK;
265 }
266
267
268
269 static const GF_FilterCapability A52DecCaps[] =
270 {
271 CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
272 CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
273 CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_AC3),
274 CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
275 };
276
277 GF_FilterRegister A52DecRegister = {
278 .name = "a52dec",
279 GF_FS_SET_DESCRIPTION("A52 decoder")
280 GF_FS_SET_HELP("This filter decodes AC3 streams through a52dec library.")
281 .private_size = sizeof(GF_A52DecCtx),
282 .priority = 1,
283 SETCAPS(A52DecCaps),
284 .configure_pid = a52dec_configure_pid,
285 .process = a52dec_process,
286 .finalize = a52dec_finalize
287 };
288
289 #endif
290
a52dec_register(GF_FilterSession * session)291 const GF_FilterRegister *a52dec_register(GF_FilterSession *session)
292 {
293 #ifdef GPAC_HAS_LIBA52
294 return &A52DecRegister;
295 #else
296 return NULL;
297 #endif
298 }
299