Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2005-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / MP3 libmad 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 :
27 : #include <gpac/filters.h>
28 :
29 : #ifdef GPAC_HAS_MAD
30 :
31 : #include <gpac/constants.h>
32 :
33 : #if defined(_WIN32_WCE) || defined(_WIN64) || defined(__SYMBIAN32__)
34 : #ifndef FPM_DEFAULT
35 : #ifdef GPAC_64_BITS
36 : #define FPM_64BIT
37 : #else
38 : #define FPM_DEFAULT
39 : #endif
40 : #endif
41 : #endif
42 :
43 : #include <mad.h>
44 :
45 : #if !defined(__GNUC__)
46 : # if defined(_WIN32_WCE) || defined (WIN32)
47 : # pragma comment(lib, "libmad")
48 : # endif
49 : #endif
50 :
51 :
52 : typedef struct
53 : {
54 : GF_FilterPid *ipid, *opid;
55 :
56 : Bool configured;
57 :
58 : u32 sample_rate, num_samples, num_channels;
59 : u32 timescale;
60 : u64 last_cts;
61 :
62 : unsigned char *buffer;
63 : u32 len;
64 :
65 : struct mad_frame frame;
66 : struct mad_stream stream;
67 : struct mad_synth synth;
68 :
69 : Bool flush_done;
70 : u32 last_pck_dur;
71 : s64 delay;
72 :
73 : } GF_MADCtx;
74 :
75 19 : static void maddec_copy_props(GF_MADCtx *ctx)
76 : {
77 : //copy properties at init or reconfig
78 19 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
79 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
80 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16) );
81 :
82 19 : if (ctx->sample_rate)
83 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
84 :
85 19 : if (ctx->num_channels) {
86 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
87 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT((ctx->num_channels==1) ? GF_AUDIO_CH_FRONT_CENTER : GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT) );
88 : }
89 :
90 19 : if (!ctx->delay)
91 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DELAY, NULL);
92 19 : }
93 :
94 19 : static GF_Err maddec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
95 : {
96 : const GF_PropertyValue *p;
97 19 : GF_MADCtx *ctx = gf_filter_get_udta(filter);
98 :
99 19 : if (is_remove) {
100 0 : if (ctx->opid) {
101 0 : gf_filter_pid_remove(ctx->opid);
102 0 : ctx->opid = NULL;
103 : }
104 0 : ctx->ipid = NULL;
105 0 : return GF_OK;
106 : }
107 19 : if (! gf_filter_pid_check_caps(pid))
108 : return GF_NOT_SUPPORTED;
109 :
110 :
111 19 : if (ctx->configured) {
112 0 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_NO_PRIMING);
113 : //no re-prime, skip if same config
114 0 : if (p && p->value.boolean) {
115 0 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
116 0 : u32 sr = p ? p->value.uint : 0;
117 0 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
118 0 : u32 ch = p ? p->value.uint : 0;
119 0 : if ((ctx->sample_rate==sr) && (ctx->num_channels==ch)) {
120 0 : maddec_copy_props(ctx);
121 0 : return GF_OK;
122 : }
123 : }
124 :
125 0 : mad_stream_finish(&ctx->stream);
126 0 : mad_frame_finish(&ctx->frame);
127 : mad_synth_finish(&ctx->synth);
128 : }
129 19 : mad_stream_init(&ctx->stream);
130 19 : mad_frame_init(&ctx->frame);
131 19 : mad_synth_init(&ctx->synth);
132 19 : ctx->configured = GF_TRUE;
133 :
134 : /*we need a frame to init, so use default values*/
135 19 : ctx->num_samples = 1152;
136 19 : ctx->num_channels = 0;
137 19 : ctx->sample_rate = 0;
138 19 : ctx->ipid = pid;
139 :
140 19 : if (!ctx->opid) {
141 19 : ctx->opid = gf_filter_pid_new(filter);
142 : }
143 :
144 19 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_SAMPLE_RATE);
145 19 : if (p) ctx->sample_rate = p->value.uint;
146 19 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_NUM_CHANNELS);
147 19 : if (p) ctx->num_channels = p->value.uint;
148 :
149 19 : if (!ctx->buffer) {
150 19 : ctx->buffer = (unsigned char*)gf_malloc(sizeof(char) * 2*MAD_BUFFER_MDLEN);
151 : }
152 :
153 19 : gf_filter_set_name(filter, "dec_mad:MAD " MAD_VERSION);
154 19 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_DELAY);
155 19 : ctx->delay = p ? p->value.longsint : 0;
156 :
157 19 : gf_filter_pid_set_framing_mode(pid, GF_TRUE);
158 :
159 19 : maddec_copy_props(ctx);
160 :
161 19 : return GF_OK;
162 : }
163 :
164 19 : static void maddec_finalize(GF_Filter *filter)
165 : {
166 19 : GF_MADCtx *ctx = gf_filter_get_udta(filter);
167 :
168 19 : if (ctx->buffer) gf_free(ctx->buffer);
169 :
170 19 : if (ctx->configured) {
171 19 : mad_stream_finish(&ctx->stream);
172 19 : mad_frame_finish(&ctx->frame);
173 : mad_synth_finish(&ctx->synth);
174 : }
175 19 : }
176 :
177 : /*from miniMad.c*/
178 : #define MAD_SCALE(ret, s_chan) \
179 : chan = s_chan; \
180 : chan += (1L << (MAD_F_FRACBITS - 16)); \
181 : if (chan >= MAD_F_ONE) \
182 : chan = MAD_F_ONE - 1; \
183 : else if (chan < -MAD_F_ONE) \
184 : chan = -MAD_F_ONE; \
185 : ret = chan >> (MAD_F_FRACBITS + 1 - 16); \
186 :
187 8483 : static GF_Err maddec_process(GF_Filter *filter)
188 : {
189 : mad_fixed_t *left_ch, *right_ch, chan;
190 : u8 *ptr;
191 : u8 *data;
192 : u32 num, samples_to_trash, in_size; //, outSize=0;
193 8483 : GF_MADCtx *ctx = gf_filter_get_udta(filter);
194 : GF_FilterPacket *dst_pck;
195 8483 : GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
196 :
197 8483 : if (!pck) {
198 2704 : if (gf_filter_pid_is_eos(ctx->ipid)) {
199 38 : if (ctx->flush_done) {
200 28 : gf_filter_pid_set_eos(ctx->opid);
201 28 : return GF_EOS;
202 : }
203 10 : ctx->flush_done = GF_TRUE;
204 10 : memset(ctx->buffer + ctx->len, 0, MAD_BUFFER_GUARD);
205 10 : ctx->len += MAD_BUFFER_GUARD;
206 : } else {
207 : return GF_OK;
208 : }
209 : } else {
210 5779 : data = (char *) gf_filter_pck_get_data(pck, &in_size);
211 :
212 5779 : if (ctx->len + in_size > 2*MAD_BUFFER_MDLEN) {
213 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[MAD] MAD buffer overflow, truncating\n"));
214 0 : in_size = 2*MAD_BUFFER_MDLEN - ctx->len;
215 : }
216 :
217 5779 : memcpy(ctx->buffer + ctx->len, data, in_size);
218 5779 : ctx->len += in_size;
219 5779 : ctx->last_pck_dur = gf_filter_pck_get_duration(pck);
220 : }
221 :
222 5789 : mad_resync:
223 5793 : mad_stream_buffer(&ctx->stream, ctx->buffer, ctx->len);
224 :
225 5793 : if (mad_frame_decode(&ctx->frame, &ctx->stream) == -1) {
226 27 : if (!pck) return GF_OK;
227 :
228 27 : if (ctx->stream.error==MAD_ERROR_BUFLEN) {
229 : if (pck) {
230 23 : ctx->last_cts = gf_filter_pck_get_cts(pck);
231 23 : ctx->timescale = gf_filter_pck_get_timescale(pck);
232 23 : gf_filter_pid_drop_packet(ctx->ipid);
233 : }
234 23 : return GF_OK;
235 : }
236 4 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[MAD] Decoding failed error %s (%d)\n", mad_stream_errorstr(&ctx->stream), ctx->stream.error ) );
237 4 : if (ctx->len==in_size) {
238 0 : if (pck) gf_filter_pid_drop_packet(ctx->ipid);
239 0 : return GF_NON_COMPLIANT_BITSTREAM;
240 : }
241 : //try resynchro
242 4 : memcpy(ctx->buffer, data, in_size);
243 4 : ctx->len = in_size;
244 4 : goto mad_resync;
245 : }
246 :
247 5766 : mad_synth_frame(&ctx->synth, &ctx->frame);
248 :
249 5766 : if ((ctx->sample_rate != ctx->synth.pcm.samplerate) || (ctx->num_channels != ctx->synth.pcm.channels) || (ctx->num_samples != ctx->synth.pcm.length)) {
250 19 : ctx->sample_rate = ctx->synth.pcm.samplerate;
251 19 : ctx->num_channels = (u8) ctx->synth.pcm.channels;
252 19 : ctx->num_samples = ctx->synth.pcm.length;
253 :
254 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(ctx->sample_rate) );
255 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(ctx->num_channels) );
256 19 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT((ctx->num_channels==1) ? GF_AUDIO_CH_FRONT_CENTER : GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT) );
257 : }
258 :
259 5766 : if (ctx->stream.next_frame) {
260 5766 : ctx->len = (u32) (&ctx->buffer[ctx->len] - ctx->stream.next_frame);
261 5766 : memmove(ctx->buffer, ctx->stream.next_frame, ctx->len);
262 : }
263 :
264 5766 : num = ctx->synth.pcm.length;
265 :
266 : samples_to_trash = 0;
267 5766 : if (ctx->delay<0) {
268 0 : if ((s64) ctx->last_cts + ctx->delay < 0) {
269 0 : s32 dur = num;
270 0 : if (ctx->timescale != ctx->sample_rate) {
271 0 : dur *= ctx->sample_rate;
272 0 : dur /= ctx->timescale;
273 : }
274 0 : if (dur + ctx->delay < 0) {
275 : num = 0;
276 0 : ctx->delay += dur;
277 : } else {
278 0 : samples_to_trash = (u32) -ctx->delay;
279 : }
280 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DELAY, NULL);
281 : } else {
282 0 : ctx->delay = 0;
283 : }
284 : }
285 :
286 5766 : if (!pck && ctx->last_pck_dur) {
287 : u32 dur = ctx->last_pck_dur;
288 10 : if (ctx->timescale != ctx->sample_rate) {
289 0 : dur *= ctx->sample_rate;
290 0 : dur /= ctx->timescale;
291 : }
292 10 : if (dur < num) {
293 : num = dur;
294 : }
295 : }
296 :
297 5766 : left_ch = ctx->synth.pcm.samples[0] + samples_to_trash;
298 5766 : right_ch = ctx->synth.pcm.samples[1] + samples_to_trash;
299 :
300 5766 : dst_pck = gf_filter_pck_new_alloc(ctx->opid, (num - samples_to_trash) * 2 * ctx->num_channels, &ptr);
301 5766 : if (!dst_pck) return GF_OUT_OF_MEM;
302 :
303 5766 : if (pck) {
304 5756 : ctx->last_cts = gf_filter_pck_get_cts(pck);
305 5756 : ctx->timescale = gf_filter_pck_get_timescale(pck);
306 5756 : gf_filter_pck_merge_properties(pck, dst_pck);
307 :
308 5756 : gf_filter_pid_drop_packet(ctx->ipid);
309 : }
310 5766 : gf_filter_pck_set_cts(dst_pck, ctx->last_cts);
311 5766 : if (ctx->timescale != ctx->sample_rate) {
312 0 : u64 dur = num * ctx->timescale;
313 0 : dur /= ctx->sample_rate;
314 0 : gf_filter_pck_set_duration(dst_pck, (u32) dur);
315 0 : ctx->last_cts += dur;
316 : } else {
317 5766 : gf_filter_pck_set_duration(dst_pck, num);
318 5766 : ctx->last_cts += num;
319 : }
320 :
321 :
322 3326982 : while (num-- > samples_to_trash) {
323 : s32 rs;
324 3321216 : MAD_SCALE(rs, (*left_ch++) );
325 :
326 3321216 : *ptr = (rs >> 0) & 0xff;
327 3321216 : ptr++;
328 3321216 : *ptr = (rs >> 8) & 0xff;
329 3321216 : ptr++;
330 : //outSize += 2;
331 :
332 3321216 : if (ctx->num_channels == 2) {
333 3321216 : MAD_SCALE(rs, (*right_ch++) );
334 3321216 : *ptr = (rs >> 0) & 0xff;
335 3321216 : ptr++;
336 3321216 : *ptr = (rs >> 8) & 0xff;
337 3321216 : ptr++;
338 : //outSize += 2;
339 : }
340 : }
341 5766 : gf_filter_pck_send(dst_pck);
342 5766 : return GF_OK;
343 : }
344 :
345 :
346 : static const GF_FilterCapability MADCaps[] =
347 : {
348 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
349 : CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
350 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG2_PART3),
351 : CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_MPEG_AUDIO),
352 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
353 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
354 : };
355 :
356 : GF_FilterRegister MADRegister = {
357 : .name = "maddec",
358 : GF_FS_SET_DESCRIPTION("MAD decoder")
359 : GF_FS_SET_HELP("This filter decodes MPEG 1/2 audio streams through libmad library.")
360 : .private_size = sizeof(GF_MADCtx),
361 : .priority = 1,
362 : SETCAPS(MADCaps),
363 : .finalize = maddec_finalize,
364 : .configure_pid = maddec_configure_pid,
365 : .process = maddec_process,
366 : };
367 :
368 : #endif
369 :
370 2877 : const GF_FilterRegister *maddec_register(GF_FilterSession *session)
371 : {
372 : #ifdef GPAC_HAS_MAD
373 2877 : return &MADRegister;
374 : #else
375 : return NULL;
376 : #endif
377 : }
378 :
|