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