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