summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames Stembridge <jstembridge@users.sourceforge.net>2005-06-04 20:29:16 +0000
committerJames Stembridge <jstembridge@users.sourceforge.net>2005-06-04 20:29:16 +0000
commitffa655e28f5854bdf0e6782ea94a03f2277d2f36 (patch)
tree15fbfbb5c0d99cff4ad94c15921ccfe628bb379b /src
parentea81e06f7ac908744a8dea6eb8cb1db164ea4c8d (diff)
downloadxine-lib-ffa655e28f5854bdf0e6782ea94a03f2277d2f36.tar.gz
xine-lib-ffa655e28f5854bdf0e6782ea94a03f2277d2f36.tar.bz2
Bring AC3 demuxer in line with DTS, support raw, cd and wav sources
CVS patchset: 7609 CVS date: 2005/06/04 20:29:16
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_ac3.c200
-rw-r--r--src/demuxers/demux_wav.c39
-rw-r--r--src/demuxers/group_audio.c4
3 files changed, 164 insertions, 79 deletions
diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c
index 9590c4b58..3bf92a804 100644
--- a/src/demuxers/demux_ac3.c
+++ b/src/demuxers/demux_ac3.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001-2003 the xine project
+ * Copyright (C) 2001-2005 the xine project
*
* This file is part of xine, a free video player.
*
@@ -23,7 +23,7 @@
* This demuxer detects raw AC3 data in a file and shovels AC3 data
* directly to the AC3 decoder.
*
- * $Id: demux_ac3.c,v 1.17 2005/06/04 12:05:28 jstembridge Exp $
+ * $Id: demux_ac3.c,v 1.18 2005/06/04 20:29:16 jstembridge Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -37,6 +37,12 @@
#include <stdlib.h>
#include <ctype.h>
+#define LOG_MODULE "demux_ac3"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
#include "xine_internal.h"
#include "xineutils.h"
#include "demux.h"
@@ -44,7 +50,8 @@
#include "bswap.h"
#include "group_audio.h"
-#define AC3_PREAMBLE_BYTES 5
+#define DATA_TAG 0x61746164
+#define PEAK_SIZE 7056 /* 3 raw cd frames */
typedef struct {
demux_plugin_t demux_plugin;
@@ -60,9 +67,10 @@ typedef struct {
int frame_size;
int running_time;
- /* This hack indicates that 2 bytes (0x0B77) have already been consumed
- * from a non-seekable stream during the detection phase. */
- int first_non_seekable_frame;
+ off_t data_start;
+
+ uint32_t buf_type;
+
} demux_ac3_t;
typedef struct {
@@ -119,42 +127,144 @@ static const struct frmsize_s frmsizecod_tbl[64] =
/* returns 1 if the AC3 file was opened successfully, 0 otherwise */
static int open_ac3_file(demux_ac3_t *this) {
- unsigned char preamble[AC3_PREAMBLE_BYTES];
+ int i;
+ int offset = 0;
+ int peak_size = 0;
+ int spdif_mode = 0;
+ uint32_t syncword = 0;
+ uint32_t blocksize;
+ uint8_t peak[PEAK_SIZE];
+
+ lprintf("open_ac3_file\n");
+
+ /* block based demuxer (i.e. cdda) will only allow reads in block
+ * sized pieces */
+ blocksize = this->input->get_blocksize(this->input);
+ if (blocksize && INPUT_IS_SEEKABLE(this->input)) {
+ int read;
+
+ this->input->seek(this->input, 0, SEEK_SET);
+ while (peak_size < PEAK_SIZE) {
+ read = this->input->read(this->input, &peak[peak_size], blocksize);
+ if (read)
+ peak_size += read;
+ else
+ break;
+ }
+ this->input->seek(this->input, 0, SEEK_SET);
+ } else {
+ peak_size = MAX_PREVIEW_SIZE;
- /* check if the sync mark matches up */
- if (_x_demux_read_header(this->input, preamble, AC3_PREAMBLE_BYTES) !=
- AC3_PREAMBLE_BYTES)
- return 0;
+ if (_x_demux_read_header(this->input, peak, peak_size) != peak_size)
+ return 0;
+ }
- if ((preamble[0] != 0x0B) ||
- (preamble[1] != 0x77))
- return 0;
+ lprintf("peak size: %d\n", peak_size);
+
+ /* Check for wav header, as we'll handle AC3 with a wav header shoved
+ * on the front for CD burning */
+ if ((peak[0] == 'R') && (peak[1] == 'I') && (peak[2] == 'F') &&
+ (peak[3] == 'F') && (peak[8] == 'W') && (peak[9] == 'A') &&
+ (peak[10] == 'V') && (peak[11] == 'E') && (peak[12] == 'f') &&
+ (peak[13] == 'm') && (peak[14] == 't') && (peak[15] == ' ')) {
+ /* Check this looks like a cd audio wav */
+ unsigned int audio_type;
+ xine_waveformatex *wave = (xine_waveformatex *) &peak[20];
+
+ _x_waveformatex_le2me(wave);
+ audio_type = _x_formattag_to_buf_audio(wave->wFormatTag);
+
+ if ((audio_type != BUF_AUDIO_LPCM_LE) || (wave->nChannels != 2) ||
+ (wave->nSamplesPerSec != 44100) || (wave->wBitsPerSample != 16))
+ return 0;
+
+ lprintf("looks like a cd audio wav file\n");
+
+ /* Find the data chunk */
+ offset = 20 + LE_32(&peak[16]);
+ while (offset < peak_size-8) {
+ unsigned int chunk_tag = LE_32(&peak[offset]);
+ unsigned int chunk_size = LE_32(&peak[offset+4]);
+
+ if (chunk_tag == DATA_TAG) {
+ offset += 8;
+ lprintf("found the start of the data at offset %d\n", offset);
+ break;
+ } else
+ offset += chunk_size;
+ }
+ }
- /* file is qualified; skip over the header bytes in the stream */
- this->input->seek(this->input, AC3_PREAMBLE_BYTES, SEEK_SET);
+ /* Look for a valid AC3 sync word */
+ for (i=offset; i<peak_size; i++) {
+ if ((syncword & 0xffff) == 0x0b77) {
+ this->data_start = i-2;
+ lprintf("found AC3 syncword at offset %d\n", i-2);
+ break;
+ }
- this->sample_rate = preamble[4] >> 6;
- if (this->sample_rate > 2)
- return 0;
+ if ((syncword == 0x72f81f4e) && (peak[i] == 0x01)) {
+ spdif_mode = 1;
+ this->data_start = i+4;
+ lprintf("found AC3 SPDIF header at offset %d\n", i-4);
+ break;
+ }
+
+ syncword = (syncword << 8) | peak[i];
+ }
- this->frame_size =
- frmsizecod_tbl[preamble[4] & 0x3F].frm_size[this->sample_rate] * 2;
+ if (i >= peak_size-2)
+ return 0;
- /* convert the sample rate to a more useful number */
- if (this->sample_rate == 0)
- this->sample_rate = 48000;
- else if (this->sample_rate == 1)
+ if (spdif_mode) {
this->sample_rate = 44100;
- else
- this->sample_rate = 32000;
+ this->frame_size = 256*6*4;
+ this->buf_type = BUF_AUDIO_DNET;
+ } else {
+ int fscod, frmsizecod;
+
+ fscod = peak[this->data_start+4] >> 6;
+ frmsizecod = peak[this->data_start+4] & 0x3F;
+
+ if ((fscod > 2) || (frmsizecod > 37))
+ return 0;
+
+ this->frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] * 2;
+
+ /* convert the sample rate to a more useful number */
+ switch (fscod) {
+ case 0:
+ this->sample_rate = 48000;
+ break;
+ case 1:
+ this->sample_rate = 44100;
+ break;
+ default:
+ this->sample_rate = 32000;
+ break;
+ }
+
+ /* Look for a second sync word */
+ if ((this->data_start+this->frame_size+1 >= peak_size) ||
+ (peak[this->data_start+this->frame_size] != 0x0b) ||
+ (peak[this->data_start+this->frame_size + 1] != 0x77)) {
+ return 0;
+ }
- this->running_time = this->input->get_length(this->input);
+ lprintf("found second AC3 sync word\n");
+
+ this->buf_type = BUF_AUDIO_A52;
+ }
+
+ this->running_time = this->input->get_length(this->input) -
+ this->data_start;
this->running_time /= this->frame_size;
this->running_time *= (90000 / 1000) * (256 * 6);
this->running_time /= this->sample_rate;
- if (!INPUT_IS_SEEKABLE(this->input))
- this->first_non_seekable_frame = 1;
+ lprintf("sample rate: %d\n", this->sample_rate);
+ lprintf("frame size: %d\n", this->frame_size);
+ lprintf("running time: %d\n", this->running_time);
return 1;
}
@@ -166,6 +276,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) {
off_t current_stream_pos;
int64_t audio_pts;
int frame_number;
+ uint32_t blocksize;
current_stream_pos = this->input->get_current_pos(this->input);
frame_number = current_stream_pos / this->frame_size;
@@ -188,15 +299,24 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) {
this->seek_flag = 0;
}
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- if (this->first_non_seekable_frame) {
- this->first_non_seekable_frame = 0;
- buf->content[0] = 0x0B;
- buf->content[1] = 0x77;
- buf->size = this->input->read(this->input, &buf->content[2],
- this->frame_size);
+ blocksize = this->input->get_blocksize(this->input);
+ if (blocksize) {
+ buf = this->input->read_block(this->input, this->audio_fifo,
+ blocksize);
+ if (!buf) {
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
} else {
- buf->size = this->input->read(this->input, buf->content, this->frame_size);
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf->size = this->input->read(this->input, buf->content,
+ this->frame_size);
+ }
+
+ if (buf->size == 0) {
+ buf->free_buffer(buf);
+ this->status = DEMUX_FINISHED;
+ return this->status;
}
if (buf->size == 0) {
@@ -205,7 +325,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) {
return this->status;
}
- buf->type = BUF_AUDIO_A52;
+ buf->type = this->buf_type;
if( this->input->get_length (this->input) )
buf->extra_info->input_normpos = (int)( (double) current_stream_pos *
65535 / this->input->get_length (this->input) );
@@ -237,7 +357,7 @@ static void demux_ac3_send_headers(demux_plugin_t *this_gen) {
/* send init info to decoders */
if (this->audio_fifo) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->type = BUF_AUDIO_A52;
+ buf->type = this->buf_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
buf->size = 0;
this->audio_fifo->put (this->audio_fifo, buf);
diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c
index 48074aa3c..e23f43aa5 100644
--- a/src/demuxers/demux_wav.c
+++ b/src/demuxers/demux_wav.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001-2003 the xine project
+ * Copyright (C) 2001-2005 the xine project
*
* This file is part of xine, a free video player.
*
@@ -22,7 +22,7 @@
* MS WAV File Demuxer by Mike Melanson (melanson@pcisys.net)
* based on WAV specs that are available far and wide
*
- * $Id: demux_wav.c,v 1.62 2005/05/28 09:34:53 jstembridge Exp $
+ * $Id: demux_wav.c,v 1.63 2005/06/04 20:29:16 jstembridge Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -146,31 +146,6 @@ static int open_wav_file(demux_wav_t *this) {
this->input->seek(this->input, chunk_size, SEEK_CUR);
}
}
- if (this->audio_type == BUF_AUDIO_LPCM_LE) {
- if (this->input->read(this->input, chunk_preamble, 6) != 6 ) {
- free (this->wave);
- return 0;
- }
- /* rewind the amount we just read */
- this->input->seek(this->input, -6, SEEK_CUR);
-
- if (chunk_preamble[0] == 0x72 &&
- chunk_preamble[1] == 0xf8 &&
- chunk_preamble[2] == 0x1f &&
- chunk_preamble[3] == 0x4e ) {
- this->audio_type = BUF_AUDIO_DNET;
- }
-#if 0
- printf("Preamble=%02x %02x %02x %02x %02x %02x\n",
- chunk_preamble[0],
- chunk_preamble[1],
- chunk_preamble[2],
- chunk_preamble[3],
- chunk_preamble[4],
- chunk_preamble[5]);
-#endif
-
- }
return 1;
}
@@ -235,16 +210,6 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) {
printf("\n");
#endif
- if (this->audio_type == BUF_AUDIO_LPCM_LE) {
- if (buf->content[0] == 0x72 &&
- buf->content[1] == 0xf8 &&
- buf->content[2] == 0x1f &&
- buf->content[3] == 0x4e ) {
- this->audio_type = BUF_AUDIO_DNET;
- }
- } else if (this->audio_type == BUF_AUDIO_DNET) {
- buf->pts=0; /* We don't need pts values for only audio streams. */
- }
#if 0
for(n=0;n<20;n++) {
printf("%x ",buf->content[n]);
diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c
index 438b71554..cce736525 100644
--- a/src/demuxers/group_audio.c
+++ b/src/demuxers/group_audio.c
@@ -19,7 +19,7 @@
*
* This file contains plugin entries for several demuxers used in games
*
- * $Id: group_audio.c,v 1.20 2005/05/29 19:20:48 jstembridge Exp $
+ * $Id: group_audio.c,v 1.21 2005/06/04 20:29:16 jstembridge Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -40,7 +40,7 @@ demuxer_info_t demux_info_aac = {
};
demuxer_info_t demux_info_ac3 = {
- 0 /* priority */
+ 8 /* priority */
};
demuxer_info_t demux_info_aud = {