Mercurial > hg > sv-dependency-builds
comparison src/libmad-0.15.1b/decoder.c @ 85:545efbb81310
Import initial set of sources
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 18 Mar 2013 14:12:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 85:545efbb81310 |
---|---|
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: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $ | |
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 } |