diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/extract_mp3.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/extract_mp3.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/extract_mp3.c b/debian/transcode/transcode-1.1.7/import/extract_mp3.c new file mode 100644 index 00000000..950bbe98 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/extract_mp3.c @@ -0,0 +1,352 @@ +/* + * extract_mp3.c + * + * Copyright (C) Thomas Oestreich - June 2001 + * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "transcode.h" +#include "libtc/libtc.h" +#include "tcinfo.h" + +#include "avilib/avilib.h" +#include "ioaux.h" +#include "tc.h" + + +#define BUFFER_SIZE 262144 +static uint8_t buffer[BUFFER_SIZE]; +static FILE *in_file, *out_file; + +static int demux_track=0xc0; + +static void ps_loop (void) +{ + static int mpeg1_skip_table[16] = { + 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + }; + + uint8_t * buf; + uint8_t * end; + uint8_t * tmp1=NULL; + uint8_t * tmp2=NULL; + int complain_loudly; + + complain_loudly = 1; + buf = buffer; + + do { + end = buf + fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file); + buf = buffer; + + //scan buffer + while (buf + 4 <= end) { + + // check for valid start code + if (buf[0] || buf[1] || (buf[2] != 0x01)) { + if (complain_loudly) { + + tc_log_warn(__FILE__, "missing start code at %#lx", + ftell (in_file) - (end - buf)); + if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0)) + tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored"); + + complain_loudly = 0; + } + buf++; + continue; + }// check for valid start code + + + switch (buf[3]) { + + case 0xb9: /* program end code */ + return; + + case 0xba: /* pack header */ + + /* skip */ + if ((buf[4] & 0xc0) == 0x40) /* mpeg2 */ + tmp1 = buf + 14 + (buf[13] & 7); + else if ((buf[4] & 0xf0) == 0x20) /* mpeg1 */ + tmp1 = buf + 12; + else if (buf + 5 > end) + goto copy; + else { + tc_log_error(__FILE__, "weird pack header"); + import_exit(1); + } + + if (tmp1 > end) + goto copy; + buf = tmp1; + break; + + //MPEG audio + + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + else { /* mpeg1 */ + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + if((buf[3] & 0xff) == demux_track) { + if (tmp1 < tmp2) { + TC_PIPE_WRITE(fileno(out_file), tmp1, tmp2-tmp1); + /* yeah, I know that's ugly -- FR */ + } + } + buf = tmp2; + + break; + + default: + if (buf[3] < 0xb9) + tc_log_warn(__FILE__, "broken stream - skipping data"); + + /* skip */ + tmp1 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp1 > end) + goto copy; + buf = tmp1; + break; + + } //start code selection + } //scan buffer + + if (buf < end) { + copy: + /* we only pass here for mpeg1 ps streams */ + memmove (buffer, buf, end - buf); + } + buf = buffer + (end - buf); + + } while (end == buffer + BUFFER_SIZE); +} + +static int mp3scan(int infd, int outfd) +{ + + int j=0, i=0, s=0; + + unsigned long k=0; + + + char *buffer = tc_malloc (SIZE_PCM_FRAME); + + uint16_t sync_word = 0; + + // need to find syncbyte: + + if (!buffer) { + tc_log_error(__FILE__, "cannot malloc memory"); + return 1; + } + + for(;;) { + + if (tc_pread(infd, &buffer[s], 1) !=1) { + //mp3 sync byte scan failed + return(ERROR_INVALID_HEADER); + } + + sync_word = (sync_word << 8) + (uint8_t) buffer[s]; + + s = (s+1)%2; + + ++i; + ++k; + + if(sync_word == 0xfffc || sync_word == 0xfffb || sync_word == 0xfffd) break; + + if(k>(1<<20)) { + tc_log_error(__FILE__, "no MP3 sync byte found within 1024 kB of stream"); + free (buffer); + return(1); + } + } + + i=i-2; + + if(verbose & TC_DEBUG) + tc_log_msg(__FILE__, "found sync frame at offset %d (%d)", i, j); + + // dump the rest + + tc_pwrite(outfd, buffer, 2); + tc_preadwrite(infd, outfd); + + free (buffer); + return(1); +} + +#define MAX_BUF 4096 +char audio[MAX_BUF]; + +/* ------------------------------------------------------------ + * + * mp3 extract thread + * + * magic: TC_MAGIC_VOB + * TC_MAGIC_AVI + * TC_MAGIC_RAW <-- default + * + * ------------------------------------------------------------*/ + + +void extract_mp3(info_t *ipipe) +{ + + int error=0; + + avi_t *avifile; + + long frames, padding, n; + off_t bytes; + //off_t fpos; + + verbose = ipipe->verbose; + + switch(ipipe->magic) { + + case TC_MAGIC_VOB: + + in_file = fdopen(ipipe->fd_in, "r"); + out_file = fdopen(ipipe->fd_out, "w"); + + demux_track = 0xc0 + ipipe->track; + + ps_loop(); + + fclose(in_file); + fclose(out_file); + + break; + + case TC_MAGIC_AVI: + + if(ipipe->stype == TC_STYPE_STDIN){ + tc_log_error(__FILE__, "invalid magic/stype - exit"); + error=1; + break; + } + + // scan file + if (ipipe->nav_seek_file) { + if(NULL == (avifile = AVI_open_indexfd(ipipe->fd_in,0,ipipe->nav_seek_file))) { + AVI_print_error("AVI open"); + break; + } + } else { + if(NULL == (avifile = AVI_open_fd(ipipe->fd_in,1))) { + AVI_print_error("AVI open"); + break; + } + } + + //set selected for multi-audio AVI-files + AVI_set_audio_track(avifile, ipipe->track); + + bytes = (off_t)AVI_audio_bytes(avifile); + padding = bytes % MAX_BUF; + frames = bytes / MAX_BUF; + + for (n=0; n<frames; ++n) { + + if(AVI_read_audio(avifile, audio, MAX_BUF)<0) { + error=1; + break; + } + + if(tc_pwrite(ipipe->fd_out, audio, MAX_BUF)!= MAX_BUF) { + error=1; + break; + } + } + + if((bytes = AVI_read_audio(avifile, audio, padding)) < padding) + error=1; + + if(tc_pwrite(ipipe->fd_out, audio, bytes)!= bytes) error=1; + + break; + + + case TC_MAGIC_RAW: + default: + + if(ipipe->magic == TC_MAGIC_UNKNOWN) + tc_log_warn(__FILE__, "no file type specified, assuming %s", + filetype(TC_MAGIC_RAW)); + + + error=mp3scan(ipipe->fd_in, ipipe->fd_out); + + break; + } + + import_exit(error); + +} |
