Diffstat (limited to 'core/multimedia/opieplayer/libmad/decoder.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmad/decoder.c | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmad/decoder.c b/core/multimedia/opieplayer/libmad/decoder.c new file mode 100644 index 0000000..dcf7cf3 --- a/dev/null +++ b/core/multimedia/opieplayer/libmad/decoder.c | |||
@@ -0,0 +1,554 @@ | |||
1 | /* | ||
2 | * mad - MPEG audio decoder | ||
3 | * Copyright (C) 2000-2001 Robert Leslie | ||
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 "libmad_config.h" | ||
24 | # else | ||
25 | # ifndef WEXITSTATUS | ||
26 | # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) | ||
27 | # endif | ||
28 | # ifndef WIFEXITED | ||
29 | # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) | ||
30 | # endif | ||
31 | # endif | ||
32 | |||
33 | # include "libmad_global.h" | ||
34 | |||
35 | # include <sys/types.h> | ||
36 | |||
37 | # ifdef HAVE_SYS_WAIT_H | ||
38 | # include <sys/wait.h> | ||
39 | # endif | ||
40 | |||
41 | # ifdef HAVE_UNISTD_H | ||
42 | # include <unistd.h> | ||
43 | # endif | ||
44 | |||
45 | # include <fcntl.h> | ||
46 | # include <stdlib.h> | ||
47 | # include <errno.h> | ||
48 | |||
49 | # include "stream.h" | ||
50 | # include "frame.h" | ||
51 | # include "synth.h" | ||
52 | # include "decoder.h" | ||
53 | |||
54 | void mad_decoder_init(struct mad_decoder *decoder, void *data, | ||
55 | enum mad_flow (*input_func)(void *, struct mad_stream *), | ||
56 | enum mad_flow (*header_func)(void *, | ||
57 | struct mad_header const *), | ||
58 | enum mad_flow (*filter_func)(void *, struct mad_frame *), | ||
59 | enum mad_flow (*output_func)(void *, | ||
60 | struct mad_header const *, | ||
61 | struct mad_pcm *), | ||
62 | enum mad_flow (*error_func)(void *, struct mad_stream *, | ||
63 | struct mad_frame *), | ||
64 | enum mad_flow (*message_func)(void *, | ||
65 | void *, unsigned int *)) | ||
66 | { | ||
67 | decoder->mode = -1; | ||
68 | |||
69 | decoder->options = 0; | ||
70 | |||
71 | decoder->async.pid = 0; | ||
72 | decoder->async.in = -1; | ||
73 | decoder->async.out = -1; | ||
74 | |||
75 | decoder->sync = 0; | ||
76 | |||
77 | decoder->cb_data = data; | ||
78 | |||
79 | decoder->input_func = input_func; | ||
80 | decoder->header_func = header_func; | ||
81 | decoder->filter_func = filter_func; | ||
82 | decoder->output_func = output_func; | ||
83 | decoder->error_func = error_func; | ||
84 | decoder->message_func = message_func; | ||
85 | } | ||
86 | |||
87 | int mad_decoder_finish(struct mad_decoder *decoder) | ||
88 | { | ||
89 | if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) { | ||
90 | pid_t pid; | ||
91 | int status; | ||
92 | |||
93 | close(decoder->async.in); | ||
94 | |||
95 | do { | ||
96 | pid = waitpid(decoder->async.pid, &status, 0); | ||
97 | } | ||
98 | while (pid == -1 && errno == EINTR); | ||
99 | |||
100 | decoder->mode = -1; | ||
101 | |||
102 | close(decoder->async.out); | ||
103 | |||
104 | decoder->async.pid = 0; | ||
105 | decoder->async.in = -1; | ||
106 | decoder->async.out = -1; | ||
107 | |||
108 | if (pid == -1) | ||
109 | return -1; | ||
110 | |||
111 | return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static | ||
118 | enum mad_flow send_io(int fd, void const *data, size_t len) | ||
119 | { | ||
120 | char const *ptr = data; | ||
121 | ssize_t count; | ||
122 | |||
123 | while (len) { | ||
124 | do { | ||
125 | count = write(fd, ptr, len); | ||
126 | } | ||
127 | while (count == -1 && errno == EINTR); | ||
128 | |||
129 | if (count == -1) | ||
130 | return MAD_FLOW_BREAK; | ||
131 | |||
132 | len -= count; | ||
133 | ptr += count; | ||
134 | } | ||
135 | |||
136 | return MAD_FLOW_CONTINUE; | ||
137 | } | ||
138 | |||
139 | static | ||
140 | enum mad_flow receive_io(int fd, void *buffer, size_t len) | ||
141 | { | ||
142 | char *ptr = buffer; | ||
143 | ssize_t count; | ||
144 | |||
145 | while (len) { | ||
146 | do { | ||
147 | count = read(fd, ptr, len); | ||
148 | } | ||
149 | while (count == -1 && errno == EINTR); | ||
150 | |||
151 | if (count == -1) | ||
152 | return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK; | ||
153 | else if (count == 0) | ||
154 | return MAD_FLOW_STOP; | ||
155 | |||
156 | len -= count; | ||
157 | ptr += count; | ||
158 | } | ||
159 | |||
160 | return MAD_FLOW_CONTINUE; | ||
161 | } | ||
162 | |||
163 | static | ||
164 | enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) | ||
165 | { | ||
166 | int flags, blocking; | ||
167 | enum mad_flow result; | ||
168 | |||
169 | flags = fcntl(fd, F_GETFL); | ||
170 | if (flags == -1) | ||
171 | return MAD_FLOW_BREAK; | ||
172 | |||
173 | blocking = flags & ~O_NONBLOCK; | ||
174 | |||
175 | if (blocking != flags && | ||
176 | fcntl(fd, F_SETFL, blocking) == -1) | ||
177 | return MAD_FLOW_BREAK; | ||
178 | |||
179 | result = receive_io(fd, buffer, len); | ||
180 | |||
181 | if (flags != blocking && | ||
182 | fcntl(fd, F_SETFL, flags) == -1) | ||
183 | return MAD_FLOW_BREAK; | ||
184 | |||
185 | return result; | ||
186 | } | ||
187 | |||
188 | static | ||
189 | enum mad_flow send(int fd, void const *message, unsigned int size) | ||
190 | { | ||
191 | enum mad_flow result; | ||
192 | |||
193 | /* send size */ | ||
194 | |||
195 | result = send_io(fd, &size, sizeof(size)); | ||
196 | |||
197 | /* send message */ | ||
198 | |||
199 | if (result == MAD_FLOW_CONTINUE) | ||
200 | result = send_io(fd, message, size); | ||
201 | |||
202 | return result; | ||
203 | } | ||
204 | |||
205 | static | ||
206 | enum mad_flow receive(int fd, void **message, unsigned int *size) | ||
207 | { | ||
208 | enum mad_flow result; | ||
209 | unsigned int actual; | ||
210 | |||
211 | if (*message == 0) | ||
212 | *size = 0; | ||
213 | |||
214 | /* receive size */ | ||
215 | |||
216 | result = receive_io(fd, &actual, sizeof(actual)); | ||
217 | |||
218 | /* receive message */ | ||
219 | |||
220 | if (result == MAD_FLOW_CONTINUE) { | ||
221 | if (actual > *size) | ||
222 | actual -= *size; | ||
223 | else { | ||
224 | *size = actual; | ||
225 | actual = 0; | ||
226 | } | ||
227 | |||
228 | if (*size > 0) { | ||
229 | if (*message == 0) { | ||
230 | *message = malloc(*size); | ||
231 | if (*message == 0) | ||
232 | return MAD_FLOW_BREAK; | ||
233 | } | ||
234 | |||
235 | result = receive_io_blocking(fd, *message, *size); | ||
236 | } | ||
237 | |||
238 | /* throw away remainder of message */ | ||
239 | |||
240 | while (actual && result == MAD_FLOW_CONTINUE) { | ||
241 | char sink[256]; | ||
242 | unsigned int len; | ||
243 | |||
244 | len = actual > sizeof(sink) ? sizeof(sink) : actual; | ||
245 | |||
246 | result = receive_io_blocking(fd, sink, len); | ||
247 | |||
248 | actual -= len; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | return result; | ||
253 | } | ||
254 | |||
255 | static | ||
256 | enum mad_flow check_message(struct mad_decoder *decoder) | ||
257 | { | ||
258 | enum mad_flow result; | ||
259 | void *message = 0; | ||
260 | unsigned int size; | ||
261 | |||
262 | result = receive(decoder->async.in, &message, &size); | ||
263 | |||
264 | if (result == MAD_FLOW_CONTINUE) { | ||
265 | if (decoder->message_func == 0) | ||
266 | size = 0; | ||
267 | else { | ||
268 | result = decoder->message_func(decoder->cb_data, message, &size); | ||
269 | |||
270 | if (result == MAD_FLOW_IGNORE || | ||
271 | result == MAD_FLOW_BREAK) | ||
272 | size = 0; | ||
273 | } | ||
274 | |||
275 | if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) | ||
276 | result = MAD_FLOW_BREAK; | ||
277 | } | ||
278 | |||
279 | if (message) | ||
280 | free(message); | ||
281 | |||
282 | return result; | ||
283 | } | ||
284 | |||
285 | static | ||
286 | enum mad_flow error_default(void *data, struct mad_stream *stream, | ||
287 | struct mad_frame *frame) | ||
288 | { | ||
289 | int *bad_last_frame = data; | ||
290 | |||
291 | switch (stream->error) { | ||
292 | case MAD_ERROR_BADCRC: | ||
293 | if (*bad_last_frame) | ||
294 | mad_frame_mute(frame); | ||
295 | else | ||
296 | *bad_last_frame = 1; | ||
297 | |||
298 | return MAD_FLOW_IGNORE; | ||
299 | |||
300 | default: | ||
301 | return MAD_FLOW_CONTINUE; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | static | ||
306 | int run_sync(struct mad_decoder *decoder) | ||
307 | { | ||
308 | enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); | ||
309 | void *error_data; | ||
310 | int bad_last_frame = 0; | ||
311 | struct mad_stream *stream; | ||
312 | struct mad_frame *frame; | ||
313 | struct mad_synth *synth; | ||
314 | int result = 0; | ||
315 | |||
316 | if (decoder->input_func == 0) | ||
317 | return 0; | ||
318 | |||
319 | if (decoder->error_func) { | ||
320 | error_func = decoder->error_func; | ||
321 | error_data = decoder->cb_data; | ||
322 | } | ||
323 | else { | ||
324 | error_func = error_default; | ||
325 | error_data = &bad_last_frame; | ||
326 | } | ||
327 | |||
328 | stream = &decoder->sync->stream; | ||
329 | frame = &decoder->sync->frame; | ||
330 | synth = &decoder->sync->synth; | ||
331 | |||
332 | mad_stream_init(stream); | ||
333 | mad_frame_init(frame); | ||
334 | mad_synth_init(synth); | ||
335 | |||
336 | mad_stream_options(stream, decoder->options); | ||
337 | |||
338 | do { | ||
339 | switch (decoder->input_func(decoder->cb_data, stream)) { | ||
340 | case MAD_FLOW_STOP: | ||
341 | goto done; | ||
342 | case MAD_FLOW_BREAK: | ||
343 | goto fail; | ||
344 | case MAD_FLOW_IGNORE: | ||
345 | continue; | ||
346 | case MAD_FLOW_CONTINUE: | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | while (1) { | ||
351 | if (decoder->mode == MAD_DECODER_MODE_ASYNC) { | ||
352 | switch (check_message(decoder)) { | ||
353 | case MAD_FLOW_IGNORE: | ||
354 | case MAD_FLOW_CONTINUE: | ||
355 | break; | ||
356 | case MAD_FLOW_BREAK: | ||
357 | goto fail; | ||
358 | case MAD_FLOW_STOP: | ||
359 | goto done; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | if (decoder->header_func) { | ||
364 | if (mad_header_decode(&frame->header, stream) == -1) { | ||
365 | if (!MAD_RECOVERABLE(stream->error)) | ||
366 | break; | ||
367 | |||
368 | switch (error_func(error_data, stream, frame)) { | ||
369 | case MAD_FLOW_STOP: | ||
370 | goto done; | ||
371 | case MAD_FLOW_BREAK: | ||
372 | goto fail; | ||
373 | case MAD_FLOW_IGNORE: | ||
374 | case MAD_FLOW_CONTINUE: | ||
375 | default: | ||
376 | continue; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | switch (decoder->header_func(decoder->cb_data, &frame->header)) { | ||
381 | case MAD_FLOW_STOP: | ||
382 | goto done; | ||
383 | case MAD_FLOW_BREAK: | ||
384 | goto fail; | ||
385 | case MAD_FLOW_IGNORE: | ||
386 | continue; | ||
387 | case MAD_FLOW_CONTINUE: | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | if (mad_frame_decode(frame, stream) == -1) { | ||
393 | if (!MAD_RECOVERABLE(stream->error)) | ||
394 | break; | ||
395 | |||
396 | switch (error_func(error_data, stream, frame)) { | ||
397 | case MAD_FLOW_STOP: | ||
398 | goto done; | ||
399 | case MAD_FLOW_BREAK: | ||
400 | goto fail; | ||
401 | case MAD_FLOW_IGNORE: | ||
402 | break; | ||
403 | case MAD_FLOW_CONTINUE: | ||
404 | default: | ||
405 | continue; | ||
406 | } | ||
407 | } | ||
408 | else | ||
409 | bad_last_frame = 0; | ||
410 | |||
411 | if (decoder->filter_func) { | ||
412 | switch (decoder->filter_func(decoder->cb_data, frame)) { | ||
413 | case MAD_FLOW_STOP: | ||
414 | goto done; | ||
415 | case MAD_FLOW_BREAK: | ||
416 | goto fail; | ||
417 | case MAD_FLOW_IGNORE: | ||
418 | continue; | ||
419 | case MAD_FLOW_CONTINUE: | ||
420 | break; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | mad_synth_frame(synth, frame); | ||
425 | |||
426 | if (decoder->output_func) { | ||
427 | switch (decoder->output_func(decoder->cb_data, | ||
428 | &frame->header, &synth->pcm)) { | ||
429 | case MAD_FLOW_STOP: | ||
430 | goto done; | ||
431 | case MAD_FLOW_BREAK: | ||
432 | goto fail; | ||
433 | case MAD_FLOW_IGNORE: | ||
434 | case MAD_FLOW_CONTINUE: | ||
435 | break; | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | while (stream->error == MAD_ERROR_BUFLEN); | ||
441 | |||
442 | fail: | ||
443 | result = -1; | ||
444 | |||
445 | done: | ||
446 | mad_synth_finish(synth); | ||
447 | mad_frame_finish(frame); | ||
448 | mad_stream_finish(stream); | ||
449 | |||
450 | return result; | ||
451 | } | ||
452 | |||
453 | static | ||
454 | int run_async(struct mad_decoder *decoder) | ||
455 | { | ||
456 | pid_t pid; | ||
457 | int ptoc[2], ctop[2], flags; | ||
458 | |||
459 | if (pipe(ptoc) == -1) | ||
460 | return -1; | ||
461 | |||
462 | if (pipe(ctop) == -1) { | ||
463 | close(ptoc[0]); | ||
464 | close(ptoc[1]); | ||
465 | return -1; | ||
466 | } | ||
467 | |||
468 | flags = fcntl(ptoc[0], F_GETFL); | ||
469 | if (flags == -1 || | ||
470 | fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) { | ||
471 | close(ctop[0]); | ||
472 | close(ctop[1]); | ||
473 | close(ptoc[0]); | ||
474 | close(ptoc[1]); | ||
475 | return -1; | ||
476 | } | ||
477 | |||
478 | pid = fork(); | ||
479 | if (pid == -1) { | ||
480 | close(ctop[0]); | ||
481 | close(ctop[1]); | ||
482 | close(ptoc[0]); | ||
483 | close(ptoc[1]); | ||
484 | return -1; | ||
485 | } | ||
486 | |||
487 | decoder->async.pid = pid; | ||
488 | |||
489 | if (pid) { | ||
490 | /* parent */ | ||
491 | |||
492 | close(ptoc[0]); | ||
493 | close(ctop[1]); | ||
494 | |||
495 | decoder->async.in = ctop[0]; | ||
496 | decoder->async.out = ptoc[1]; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /* child */ | ||
502 | |||
503 | close(ptoc[1]); | ||
504 | close(ctop[0]); | ||
505 | |||
506 | decoder->async.in = ptoc[0]; | ||
507 | decoder->async.out = ctop[1]; | ||
508 | |||
509 | _exit(run_sync(decoder)); | ||
510 | |||
511 | /* not reached */ | ||
512 | return -1; | ||
513 | } | ||
514 | |||
515 | int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) | ||
516 | { | ||
517 | int result; | ||
518 | int (*run)(struct mad_decoder *) = 0; | ||
519 | |||
520 | switch (decoder->mode = mode) { | ||
521 | case MAD_DECODER_MODE_SYNC: | ||
522 | run = run_sync; | ||
523 | break; | ||
524 | |||
525 | case MAD_DECODER_MODE_ASYNC: | ||
526 | run = run_async; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | if (run == 0) | ||
531 | return -1; | ||
532 | |||
533 | decoder->sync = malloc(sizeof(*decoder->sync)); | ||
534 | if (decoder->sync == 0) | ||
535 | return -1; | ||
536 | |||
537 | result = run(decoder); | ||
538 | |||
539 | free(decoder->sync); | ||
540 | decoder->sync = 0; | ||
541 | |||
542 | return result; | ||
543 | } | ||
544 | |||
545 | int mad_decoder_message(struct mad_decoder *decoder, | ||
546 | void *message, unsigned int *len) | ||
547 | { | ||
548 | if (decoder->mode != MAD_DECODER_MODE_ASYNC || | ||
549 | send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE || | ||
550 | receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE) | ||
551 | return -1; | ||
552 | |||
553 | return 0; | ||
554 | } | ||