MP3 Player without external hardware MP3 Player without external hardware. A software based MP3 player based on a modified version of libmad. Mono output (at the moment) via AnalogOut. Files are read from an USB drive. This is a demo program, it plays only one file at the moment. Documentation is in "main.cpp" and "config.h"

Dependencies:   mbed

Committer:
Gruenfrosch
Date:
Fri Nov 26 12:18:30 2010 +0000
Revision:
0:7627c79db971
Child:
2:f28cf0afd021
First Version

Who changed what in which revision?

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