annotate src/libmad-0.15.1b/decoder.c @ 83:ae30d91d2ffe

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