diff options
author | Dave Chapman <dave@dchapman.com> | 2005-02-15 18:29:42 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2005-02-15 18:29:42 +0000 |
commit | 98c4f65f3a6c0de9a0bc24db38757939cb851115 (patch) | |
tree | 605bc7b4c01e9b3ed689b0edf871a543a06166bc /apps/codecs/libmad/decoder.c | |
parent | 6416099f3fb486f21caea3673a362b63e26dd314 (diff) | |
download | rockbox-98c4f65f3a6c0de9a0bc24db38757939cb851115.tar.gz rockbox-98c4f65f3a6c0de9a0bc24db38757939cb851115.zip |
Initial check-in of unmodified libmad code (libmad-0.15.1b)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5955 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libmad/decoder.c')
-rw-r--r-- | apps/codecs/libmad/decoder.c | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/apps/codecs/libmad/decoder.c b/apps/codecs/libmad/decoder.c new file mode 100644 index 0000000000..efa95e31c8 --- /dev/null +++ b/apps/codecs/libmad/decoder.c | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * libmad - MPEG audio decoder library | ||
3 | * Copyright (C) 2000-2004 Underbit Technologies, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * $Id$ | ||
20 | */ | ||
21 | |||
22 | # ifdef HAVE_CONFIG_H | ||
23 | # include "config.h" | ||
24 | # endif | ||
25 | |||
26 | # include "global.h" | ||
27 | |||
28 | # ifdef HAVE_SYS_TYPES_H | ||
29 | # include <sys/types.h> | ||
30 | # endif | ||
31 | |||
32 | # ifdef HAVE_SYS_WAIT_H | ||
33 | # include <sys/wait.h> | ||
34 | # endif | ||
35 | |||
36 | # ifdef HAVE_UNISTD_H | ||
37 | # include <unistd.h> | ||
38 | # endif | ||
39 | |||
40 | # ifdef HAVE_FCNTL_H | ||
41 | # include <fcntl.h> | ||
42 | # endif | ||
43 | |||
44 | # include <stdlib.h> | ||
45 | |||
46 | # ifdef HAVE_ERRNO_H | ||
47 | # include <errno.h> | ||
48 | # endif | ||
49 | |||
50 | # include "stream.h" | ||
51 | # include "frame.h" | ||
52 | # include "synth.h" | ||
53 | # include "decoder.h" | ||
54 | |||
55 | /* | ||
56 | * NAME: decoder->init() | ||
57 | * DESCRIPTION: initialize a decoder object with callback routines | ||
58 | */ | ||
59 | void mad_decoder_init(struct mad_decoder *decoder, void *data, | ||
60 | enum mad_flow (*input_func)(void *, | ||
61 | struct mad_stream *), | ||
62 | enum mad_flow (*header_func)(void *, | ||
63 | struct mad_header const *), | ||
64 | enum mad_flow (*filter_func)(void *, | ||
65 | struct mad_stream const *, | ||
66 | struct mad_frame *), | ||
67 | enum mad_flow (*output_func)(void *, | ||
68 | struct mad_header const *, | ||
69 | struct mad_pcm *), | ||
70 | enum mad_flow (*error_func)(void *, | ||
71 | struct mad_stream *, | ||
72 | struct mad_frame *), | ||
73 | enum mad_flow (*message_func)(void *, | ||
74 | void *, unsigned int *)) | ||
75 | { | ||
76 | decoder->mode = -1; | ||
77 | |||
78 | decoder->options = 0; | ||
79 | |||
80 | decoder->async.pid = 0; | ||
81 | decoder->async.in = -1; | ||
82 | decoder->async.out = -1; | ||
83 | |||
84 | decoder->sync = 0; | ||
85 | |||
86 | decoder->cb_data = data; | ||
87 | |||
88 | decoder->input_func = input_func; | ||
89 | decoder->header_func = header_func; | ||
90 | decoder->filter_func = filter_func; | ||
91 | decoder->output_func = output_func; | ||
92 | decoder->error_func = error_func; | ||
93 | decoder->message_func = message_func; | ||
94 | } | ||
95 | |||
96 | int mad_decoder_finish(struct mad_decoder *decoder) | ||
97 | { | ||
98 | # if defined(USE_ASYNC) | ||
99 | if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) { | ||
100 | pid_t pid; | ||
101 | int status; | ||
102 | |||
103 | close(decoder->async.in); | ||
104 | |||
105 | do | ||
106 | pid = waitpid(decoder->async.pid, &status, 0); | ||
107 | while (pid == -1 && errno == EINTR); | ||
108 | |||
109 | decoder->mode = -1; | ||
110 | |||
111 | close(decoder->async.out); | ||
112 | |||
113 | decoder->async.pid = 0; | ||
114 | decoder->async.in = -1; | ||
115 | decoder->async.out = -1; | ||
116 | |||
117 | if (pid == -1) | ||
118 | return -1; | ||
119 | |||
120 | return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0; | ||
121 | } | ||
122 | # endif | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | # if defined(USE_ASYNC) | ||
128 | static | ||
129 | enum mad_flow send_io(int fd, void const *data, size_t len) | ||
130 | { | ||
131 | char const *ptr = data; | ||
132 | ssize_t count; | ||
133 | |||
134 | while (len) { | ||
135 | do | ||
136 | count = write(fd, ptr, len); | ||
137 | while (count == -1 && errno == EINTR); | ||
138 | |||
139 | if (count == -1) | ||
140 | return MAD_FLOW_BREAK; | ||
141 | |||
142 | len -= count; | ||
143 | ptr += count; | ||
144 | } | ||
145 | |||
146 | return MAD_FLOW_CONTINUE; | ||
147 | } | ||
148 | |||
149 | static | ||
150 | enum mad_flow receive_io(int fd, void *buffer, size_t len) | ||
151 | { | ||
152 | char *ptr = buffer; | ||
153 | ssize_t count; | ||
154 | |||
155 | while (len) { | ||
156 | do | ||
157 | count = read(fd, ptr, len); | ||
158 | while (count == -1 && errno == EINTR); | ||
159 | |||
160 | if (count == -1) | ||
161 | return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK; | ||
162 | else if (count == 0) | ||
163 | return MAD_FLOW_STOP; | ||
164 | |||
165 | len -= count; | ||
166 | ptr += count; | ||
167 | } | ||
168 | |||
169 | return MAD_FLOW_CONTINUE; | ||
170 | } | ||
171 | |||
172 | static | ||
173 | enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) | ||
174 | { | ||
175 | int flags, blocking; | ||
176 | enum mad_flow result; | ||
177 | |||
178 | flags = fcntl(fd, F_GETFL); | ||
179 | if (flags == -1) | ||
180 | return MAD_FLOW_BREAK; | ||
181 | |||
182 | blocking = flags & ~O_NONBLOCK; | ||
183 | |||
184 | if (blocking != flags && | ||
185 | fcntl(fd, F_SETFL, blocking) == -1) | ||
186 | return MAD_FLOW_BREAK; | ||
187 | |||
188 | result = receive_io(fd, buffer, len); | ||
189 | |||
190 | if (flags != blocking && | ||
191 | fcntl(fd, F_SETFL, flags) == -1) | ||
192 | return MAD_FLOW_BREAK; | ||
193 | |||
194 | return result; | ||
195 | } | ||
196 | |||
197 | static | ||
198 | enum mad_flow send(int fd, void const *message, unsigned int size) | ||
199 | { | ||
200 | enum mad_flow result; | ||
201 | |||
202 | /* send size */ | ||
203 | |||
204 | result = send_io(fd, &size, sizeof(size)); | ||
205 | |||
206 | /* send message */ | ||
207 | |||
208 | if (result == MAD_FLOW_CONTINUE) | ||
209 | result = send_io(fd, message, size); | ||
210 | |||
211 | return result; | ||
212 | } | ||
213 | |||
214 | static | ||
215 | enum mad_flow receive(int fd, void **message, unsigned int *size) | ||
216 | { | ||
217 | enum mad_flow result; | ||
218 | unsigned int actual; | ||
219 | |||
220 | if (*message == 0) | ||
221 | *size = 0; | ||
222 | |||
223 | /* receive size */ | ||
224 | |||
225 | result = receive_io(fd, &actual, sizeof(actual)); | ||
226 | |||
227 | /* receive message */ | ||
228 | |||
229 | if (result == MAD_FLOW_CONTINUE) { | ||
230 | if (actual > *size) | ||
231 | actual -= *size; | ||
232 | else { | ||
233 | *size = actual; | ||
234 | actual = 0; | ||
235 | } | ||
236 | |||
237 | if (*size > 0) { | ||
238 | if (*message == 0) { | ||
239 | *message = malloc(*size); | ||
240 | if (*message == 0) | ||
241 | return MAD_FLOW_BREAK; | ||
242 | } | ||
243 | |||
244 | result = receive_io_blocking(fd, *message, *size); | ||
245 | } | ||
246 | |||
247 | /* throw away remainder of message */ | ||
248 | |||
249 | while (actual && result == MAD_FLOW_CONTINUE) { | ||
250 | char sink[256]; | ||
251 | unsigned int len; | ||
252 | |||
253 | len = actual > sizeof(sink) ? sizeof(sink) : actual; | ||
254 | |||
255 | result = receive_io_blocking(fd, sink, len); | ||
256 | |||
257 | actual -= len; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return result; | ||
262 | } | ||
263 | |||
264 | static | ||
265 | enum mad_flow check_message(struct mad_decoder *decoder) | ||
266 | { | ||
267 | enum mad_flow result; | ||
268 | void *message = 0; | ||
269 | unsigned int size; | ||
270 | |||
271 | result = receive(decoder->async.in, &message, &size); | ||
272 | |||
273 | if (result == MAD_FLOW_CONTINUE) { | ||
274 | if (decoder->message_func == 0) | ||
275 | size = 0; | ||
276 | else { | ||
277 | result = decoder->message_func(decoder->cb_data, message, &size); | ||
278 | |||
279 | if (result == MAD_FLOW_IGNORE || | ||
280 | result == MAD_FLOW_BREAK) | ||
281 | size = 0; | ||
282 | } | ||
283 | |||
284 | if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) | ||
285 | result = MAD_FLOW_BREAK; | ||
286 | } | ||
287 | |||
288 | if (message) | ||
289 | free(message); | ||
290 | |||
291 | return result; | ||
292 | } | ||
293 | # endif | ||
294 | |||
295 | static | ||
296 | enum mad_flow error_default(void *data, struct mad_stream *stream, | ||
297 | struct mad_frame *frame) | ||
298 | { | ||
299 | int *bad_last_frame = data; | ||
300 | |||
301 | switch (stream->error) { | ||
302 | case MAD_ERROR_BADCRC: | ||
303 | if (*bad_last_frame) | ||
304 | mad_frame_mute(frame); | ||
305 | else | ||
306 | *bad_last_frame = 1; | ||
307 | |||
308 | return MAD_FLOW_IGNORE; | ||
309 | |||
310 | default: | ||
311 | return MAD_FLOW_CONTINUE; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | static | ||
316 | int run_sync(struct mad_decoder *decoder) | ||
317 | { | ||
318 | enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); | ||
319 | void *error_data; | ||
320 | int bad_last_frame = 0; | ||
321 | struct mad_stream *stream; | ||
322 | struct mad_frame *frame; | ||
323 | struct mad_synth *synth; | ||
324 | int result = 0; | ||
325 | |||
326 | if (decoder->input_func == 0) | ||
327 | return 0; | ||
328 | |||
329 | if (decoder->error_func) { | ||
330 | error_func = decoder->error_func; | ||
331 | error_data = decoder->cb_data; | ||
332 | } | ||
333 | else { | ||
334 | error_func = error_default; | ||
335 | error_data = &bad_last_frame; | ||
336 | } | ||
337 | |||
338 | stream = &decoder->sync->stream; | ||
339 | frame = &decoder->sync->frame; | ||
340 | synth = &decoder->sync->synth; | ||
341 | |||
342 | mad_stream_init(stream); | ||
343 | mad_frame_init(frame); | ||
344 | mad_synth_init(synth); | ||
345 | |||
346 | mad_stream_options(stream, decoder->options); | ||
347 | |||
348 | do { | ||
349 | switch (decoder->input_func(decoder->cb_data, stream)) { | ||
350 | case MAD_FLOW_STOP: | ||
351 | goto done; | ||
352 | case MAD_FLOW_BREAK: | ||
353 | goto fail; | ||
354 | case MAD_FLOW_IGNORE: | ||
355 | continue; | ||
356 | case MAD_FLOW_CONTINUE: | ||
357 | break; | ||
358 | } | ||
359 | |||
360 | while (1) { | ||
361 | # if defined(USE_ASYNC) | ||
362 | if (decoder->mode == MAD_DECODER_MODE_ASYNC) { | ||
363 | switch (check_message(decoder)) { | ||
364 | case MAD_FLOW_IGNORE: | ||
365 | case MAD_FLOW_CONTINUE: | ||
366 | break; | ||
367 | case MAD_FLOW_BREAK: | ||
368 | goto fail; | ||
369 | case MAD_FLOW_STOP: | ||
370 | goto done; | ||
371 | } | ||
372 | } | ||
373 | # endif | ||
374 | |||
375 | if (decoder->header_func) { | ||
376 | if (mad_header_decode(&frame->header, stream) == -1) { | ||
377 | if (!MAD_RECOVERABLE(stream->error)) | ||
378 | break; | ||
379 | |||
380 | switch (error_func(error_data, stream, frame)) { | ||
381 | case MAD_FLOW_STOP: | ||
382 | goto done; | ||
383 | case MAD_FLOW_BREAK: | ||
384 | goto fail; | ||
385 | case MAD_FLOW_IGNORE: | ||
386 | case MAD_FLOW_CONTINUE: | ||
387 | default: | ||
388 | continue; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | switch (decoder->header_func(decoder->cb_data, &frame->header)) { | ||
393 | case MAD_FLOW_STOP: | ||
394 | goto done; | ||
395 | case MAD_FLOW_BREAK: | ||
396 | goto fail; | ||
397 | case MAD_FLOW_IGNORE: | ||
398 | continue; | ||
399 | case MAD_FLOW_CONTINUE: | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | if (mad_frame_decode(frame, stream) == -1) { | ||
405 | if (!MAD_RECOVERABLE(stream->error)) | ||
406 | break; | ||
407 | |||
408 | switch (error_func(error_data, stream, frame)) { | ||
409 | case MAD_FLOW_STOP: | ||
410 | goto done; | ||
411 | case MAD_FLOW_BREAK: | ||
412 | goto fail; | ||
413 | case MAD_FLOW_IGNORE: | ||
414 | break; | ||
415 | case MAD_FLOW_CONTINUE: | ||
416 | default: | ||
417 | continue; | ||
418 | } | ||
419 | } | ||
420 | else | ||
421 | bad_last_frame = 0; | ||
422 | |||
423 | if (decoder->filter_func) { | ||
424 | switch (decoder->filter_func(decoder->cb_data, stream, frame)) { | ||
425 | case MAD_FLOW_STOP: | ||
426 | goto done; | ||
427 | case MAD_FLOW_BREAK: | ||
428 | goto fail; | ||
429 | case MAD_FLOW_IGNORE: | ||
430 | continue; | ||
431 | case MAD_FLOW_CONTINUE: | ||
432 | break; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | mad_synth_frame(synth, frame); | ||
437 | |||
438 | if (decoder->output_func) { | ||
439 | switch (decoder->output_func(decoder->cb_data, | ||
440 | &frame->header, &synth->pcm)) { | ||
441 | case MAD_FLOW_STOP: | ||
442 | goto done; | ||
443 | case MAD_FLOW_BREAK: | ||
444 | goto fail; | ||
445 | case MAD_FLOW_IGNORE: | ||
446 | case MAD_FLOW_CONTINUE: | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | } | ||
452 | while (stream->error == MAD_ERROR_BUFLEN); | ||
453 | |||
454 | fail: | ||
455 | result = -1; | ||
456 | |||
457 | done: | ||
458 | mad_synth_finish(synth); | ||
459 | mad_frame_finish(frame); | ||
460 | mad_stream_finish(stream); | ||
461 | |||
462 | return result; | ||
463 | } | ||
464 | |||
465 | # if defined(USE_ASYNC) | ||
466 | static | ||
467 | int run_async(struct mad_decoder *decoder) | ||
468 | { | ||
469 | pid_t pid; | ||
470 | int ptoc[2], ctop[2], flags; | ||
471 | |||
472 | if (pipe(ptoc) == -1) | ||
473 | return -1; | ||
474 | |||
475 | if (pipe(ctop) == -1) { | ||
476 | close(ptoc[0]); | ||
477 | close(ptoc[1]); | ||
478 | return -1; | ||
479 | } | ||
480 | |||
481 | flags = fcntl(ptoc[0], F_GETFL); | ||
482 | if (flags == -1 || | ||
483 | fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) { | ||
484 | close(ctop[0]); | ||
485 | close(ctop[1]); | ||
486 | close(ptoc[0]); | ||
487 | close(ptoc[1]); | ||
488 | return -1; | ||
489 | } | ||
490 | |||
491 | pid = fork(); | ||
492 | if (pid == -1) { | ||
493 | close(ctop[0]); | ||
494 | close(ctop[1]); | ||
495 | close(ptoc[0]); | ||
496 | close(ptoc[1]); | ||
497 | return -1; | ||
498 | } | ||
499 | |||
500 | decoder->async.pid = pid; | ||
501 | |||
502 | if (pid) { | ||
503 | /* parent */ | ||
504 | |||
505 | close(ptoc[0]); | ||
506 | close(ctop[1]); | ||
507 | |||
508 | decoder->async.in = ctop[0]; | ||
509 | decoder->async.out = ptoc[1]; | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | /* child */ | ||
515 | |||
516 | close(ptoc[1]); | ||
517 | close(ctop[0]); | ||
518 | |||
519 | decoder->async.in = ptoc[0]; | ||
520 | decoder->async.out = ctop[1]; | ||
521 | |||
522 | _exit(run_sync(decoder)); | ||
523 | |||
524 | /* not reached */ | ||
525 | return -1; | ||
526 | } | ||
527 | # endif | ||
528 | |||
529 | /* | ||
530 | * NAME: decoder->run() | ||
531 | * DESCRIPTION: run the decoder thread either synchronously or asynchronously | ||
532 | */ | ||
533 | int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) | ||
534 | { | ||
535 | int result; | ||
536 | int (*run)(struct mad_decoder *) = 0; | ||
537 | |||
538 | switch (decoder->mode = mode) { | ||
539 | case MAD_DECODER_MODE_SYNC: | ||
540 | run = run_sync; | ||
541 | break; | ||
542 | |||
543 | case MAD_DECODER_MODE_ASYNC: | ||
544 | # if defined(USE_ASYNC) | ||
545 | run = run_async; | ||
546 | # endif | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | if (run == 0) | ||
551 | return -1; | ||
552 | |||
553 | decoder->sync = malloc(sizeof(*decoder->sync)); | ||
554 | if (decoder->sync == 0) | ||
555 | return -1; | ||
556 | |||
557 | result = run(decoder); | ||
558 | |||
559 | free(decoder->sync); | ||
560 | decoder->sync = 0; | ||
561 | |||
562 | return result; | ||
563 | } | ||
564 | |||
565 | /* | ||
566 | * NAME: decoder->message() | ||
567 | * DESCRIPTION: send a message to and receive a reply from the decoder process | ||
568 | */ | ||
569 | int mad_decoder_message(struct mad_decoder *decoder, | ||
570 | void *message, unsigned int *len) | ||
571 | { | ||
572 | # if defined(USE_ASYNC) | ||
573 | if (decoder->mode != MAD_DECODER_MODE_ASYNC || | ||
574 | send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE || | ||
575 | receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE) | ||
576 | return -1; | ||
577 | |||
578 | return 0; | ||
579 | # else | ||
580 | return -1; | ||
581 | # endif | ||
582 | } | ||