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