summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2010-01-06 21:21:02 +0000
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2010-01-06 21:21:02 +0000
commita65a9e72c0273fee579788f57c48b27ef933a9a7 (patch)
tree1cf35c2af2c5905d773b237452067e967be64ea1
parent9a472d6a7f6f24dce5ff9a66aeed99662359ad4e (diff)
parentf717a1a9d3191948f79e6f67a76f8010671dc992 (diff)
downloadxine-lib-a65a9e72c0273fee579788f57c48b27ef933a9a7.tar.gz
xine-lib-a65a9e72c0273fee579788f57c48b27ef933a9a7.tar.bz2
Merge from 1.1.
--HG-- rename : src/libxineadec/xine_lpcm_decoder.c => src/audio_dec/xine_lpcm_decoder.c
-rw-r--r--src/audio_dec/xine_lpcm_decoder.c128
-rw-r--r--src/demuxers/demux_ts.c17
-rw-r--r--src/demuxers/demux_tta.c66
3 files changed, 164 insertions, 47 deletions
diff --git a/src/audio_dec/xine_lpcm_decoder.c b/src/audio_dec/xine_lpcm_decoder.c
index f5e2aeb6d..ca7802b07 100644
--- a/src/audio_dec/xine_lpcm_decoder.c
+++ b/src/audio_dec/xine_lpcm_decoder.c
@@ -67,22 +67,34 @@ typedef struct lpcm_decoder_s {
uint32_t ao_cap_mode;
int output_open;
- int cpu_be; /**< TRUE, if we're a Big endian CPU */
+ int cpu_be; /* TRUE, if we're a Big endian CPU */
+
+ int64_t pts;
+
+ uint8_t *buf;
+ size_t buffered_bytes;
+ size_t buf_size;
+
} lpcm_decoder_t;
static void lpcm_reset (audio_decoder_t *this_gen) {
- /* lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; */
+ lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
+ free (this->buf);
+ this->buf = NULL;
}
static void lpcm_discontinuity (audio_decoder_t *this_gen) {
+
+ lpcm_reset(this_gen);
}
static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
int16_t *sample_buffer=(int16_t *)buf->content;
+ int buf_size = buf->size;
int stream_be;
audio_buffer_t *audio_buffer;
int format_changed = 0;
@@ -98,17 +110,54 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
unsigned int sample_rate = 0;
unsigned int num_channels;
- num_channels = (buf->decoder_info[2] & 0x7) + 1;
- switch ((buf->decoder_info[2]>>4) & 3) {
- case 0: sample_rate = 48000; break;
- case 1: sample_rate = 96000; break;
- case 2: sample_rate = 44100; break;
- case 3: sample_rate = 32000; break;
- }
- switch ((buf->decoder_info[2]>>6) & 3) {
- case 0: bits_per_sample = 16; break;
- case 1: bits_per_sample = 20; break;
- case 2: bits_per_sample = 24; break;
+ lprintf("lpcm_decoder: config data 0x%x\n", buf->decoder_info[2]);
+
+ /* BluRay PCM header is 4 bytes */
+ if (buf->decoder_info[2] & 0xffffff00) {
+ static const uint8_t channels[16] = {0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0};
+
+ num_channels = channels[(buf->decoder_info[2] >> (16+4)) & 0x0f];
+ switch ((buf->decoder_info[2] >> (24+6)) & 0x03) {
+ case 1: bits_per_sample = 16; break;
+ case 2: bits_per_sample = 20; break;
+ case 3: bits_per_sample = 24; break;
+ default: bits_per_sample = 0; break;
+ }
+ switch ((buf->decoder_info[2] >> 16) & 0x0f) {
+ case 1: sample_rate = 48000; break;
+ case 4: sample_rate = 96000; break;
+ case 5: sample_rate = 192000; break;
+ default: sample_rate = 0; break;
+ }
+
+ if (!num_channels || !sample_rate || !bits_per_sample)
+ xine_log (this->stream->xine, XINE_LOG_MSG,
+ "lpcm_decoder: unsupported BluRay PCM format: 0x%08x\n", buf->decoder_info[2]);
+
+ if (this->buffered_bytes)
+ xine_log (this->stream->xine, XINE_LOG_MSG, "lpcm_decoder: %zd bytes lost !\n", this->buffered_bytes);
+
+ if (!this->buf) {
+ this->buffered_bytes = 0;
+ this->buf_size = 8128;
+ this->buf = malloc(this->buf_size);
+ }
+
+ } else {
+
+ /* MPEG2/DVD PCM header is one byte */
+ num_channels = (buf->decoder_info[2] & 0x7) + 1;
+ switch ((buf->decoder_info[2]>>4) & 3) {
+ case 0: sample_rate = 48000; break;
+ case 1: sample_rate = 96000; break;
+ case 2: sample_rate = 44100; break;
+ case 3: sample_rate = 32000; break;
+ }
+ switch ((buf->decoder_info[2]>>6) & 3) {
+ case 0: bits_per_sample = 16; break;
+ case 1: bits_per_sample = 20; break;
+ case 2: bits_per_sample = 24; break;
+ }
}
if( this->bits_per_sample != bits_per_sample ||
@@ -119,13 +168,17 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
this->number_of_channels = num_channels;
this->rate = sample_rate;
format_changed++;
+
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "lpcm_decoder: format changed to %d channels, %d bits per sample, %d Hz, %d kbit/s\n",
+ num_channels, bits_per_sample, sample_rate, (num_channels * sample_rate * bits_per_sample)/1024);
}
}
if( buf->decoder_flags & BUF_FLAG_STDHEADER ) {
this->rate=buf->decoder_info[1];
- this->bits_per_sample=buf->decoder_info[2] ;
- this->number_of_channels=buf->decoder_info[3] ;
+ this->bits_per_sample=buf->decoder_info[2];
+ this->number_of_channels=buf->decoder_info[3];
format_changed++;
}
@@ -159,6 +212,30 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
if (!this->output_open || (buf->decoder_flags & BUF_FLAG_HEADER) )
return;
+ if (buf->pts && !this->pts)
+ this->pts = buf->pts;
+
+ /* data accumulation */
+ if (this->buf) {
+ int frame_end = buf->decoder_flags & BUF_FLAG_FRAME_END;
+ if (this->buffered_bytes || !frame_end) {
+ if (this->buf_size < this->buffered_bytes + buf->size) {
+ this->buf_size *= 2;
+ this->buf = realloc(this->buf, this->buf_size);
+ }
+
+ memcpy(this->buf + this->buffered_bytes, buf->content, buf->size);
+ this->buffered_bytes += buf->size;
+
+ if (!frame_end)
+ return;
+
+ sample_buffer = (int16_t*)this->buf;
+ buf_size = this->buffered_bytes;
+ this->buffered_bytes = 0;
+ }
+ }
+
audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out);
/* Swap LPCM samples into native byte order, if necessary */
@@ -167,14 +244,14 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
if( this->bits_per_sample == 16 ){
if (stream_be != this->cpu_be)
- swab (sample_buffer, audio_buffer->mem, buf->size);
+ swab (sample_buffer, audio_buffer->mem, buf_size);
else
- memcpy (audio_buffer->mem, sample_buffer, buf->size);
+ memcpy (audio_buffer->mem, sample_buffer, buf_size);
}
else if( this->bits_per_sample == 20 ) {
uint8_t *s = (uint8_t *)sample_buffer;
uint8_t *d = (uint8_t *)audio_buffer->mem;
- int n = buf->size;
+ int n = buf_size;
if (stream_be != this->cpu_be) {
while( n >= 0 ) {
@@ -194,7 +271,7 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
} else if( this->bits_per_sample == 24 ) {
uint8_t *s = (uint8_t *)sample_buffer;
uint8_t *d = (uint8_t *)audio_buffer->mem;
- int n = buf->size;
+ int n = buf_size;
while (n >= 3) {
if ( stream_be ) {
@@ -221,18 +298,19 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
n -= 3;
}
- if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf->size )
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes\n", (int)(buf->size - (d - (uint8_t*)audio_buffer->mem))/2*3);
+ if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf_size )
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes\n", (int)(buf_size - (d - (uint8_t*)audio_buffer->mem))/2*3);
} else {
- memcpy (audio_buffer->mem, sample_buffer, buf->size);
+ memcpy (audio_buffer->mem, sample_buffer, buf_size);
}
- audio_buffer->vpts = buf->pts;
- audio_buffer->num_frames = (((buf->size*8)/this->number_of_channels)/this->bits_per_sample);
+ audio_buffer->vpts = this->pts;
+ audio_buffer->num_frames = (((buf_size*8)/this->number_of_channels)/this->bits_per_sample);
this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream);
+ this->pts = 0;
}
static void lpcm_dispose (audio_decoder_t *this_gen) {
@@ -242,6 +320,8 @@ static void lpcm_dispose (audio_decoder_t *this_gen) {
this->stream->audio_out->close (this->stream->audio_out, this->stream);
this->output_open = 0;
+ free (this->buf);
+
free (this_gen);
}
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index 3e15b2907..9053db60d 100644
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -807,6 +807,18 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
m->type |= BUF_AUDIO_DTS;
return 1;
+ } else if (m->descriptor_tag == HDMV_AUDIO_80_PCM) {
+
+ m->content = p + 4;
+ m->size = packet_len - 4;
+ m->type |= BUF_AUDIO_LPCM_BE;
+
+ m->buf->decoder_flags |= BUF_FLAG_SPECIAL;
+ m->buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
+ m->buf->decoder_info[2] = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+
+ return 1;
+
} else if (m->descriptor_tag == ISO_13818_PES_PRIVATE
&& p[0] == 0x20 && p[1] == 0x00) {
/* DVBSUB */
@@ -1525,7 +1537,10 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
demux_ts_get_reg_desc(this, &format_identifier,
stream + 5, stream_info_length);
/* If no format identifier, assume A52 */
- if ((format_identifier == 0x41432d33) || (format_identifier == 0)) {
+ if (( format_identifier == 0x41432d33) ||
+ ( format_identifier == 0) ||
+ ((format_identifier == 0x48444d56 || this->hdmv>0) && stream[0] == HDMV_AUDIO_80_PCM) /* BluRay PCM */) {
+
demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo, stream[0]);
this->audio_tracks[this->audio_tracks_count].pid = pid;
this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c
index 8f8f954d5..ada6cab30 100644
--- a/src/demuxers/demux_tta.c
+++ b/src/demuxers/demux_tta.c
@@ -65,7 +65,7 @@ typedef struct {
uint16_t channels;
uint16_t bits_per_sample;
uint32_t samplerate;
- uint32_t data_length;
+ uint32_t data_length; /* Number of samples */
uint32_t crc32;
} XINE_PACKED tta;
uint8_t buffer[22]; /* This is the size of the header */
@@ -114,7 +114,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
demux_tta_t *this = (demux_tta_t *) this_gen;
uint32_t bytes_to_read;
- if ( this->currentframe > this->totalframes ) {
+ if ( this->currentframe >= this->totalframes ) {
this->status = DEMUX_FINISHED;
return this->status;
}
@@ -129,7 +129,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
buf->type = BUF_AUDIO_TTA;
buf->pts = 0;
- buf->extra_info->total_time = this->totalframes;
+ buf->extra_info->total_time = (int)(le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate)); /* milliseconds */
buf->decoder_flags = 0;
/* Set normalised position */
@@ -163,6 +163,12 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
static void demux_tta_send_headers(demux_plugin_t *this_gen) {
demux_tta_t *this = (demux_tta_t *) this_gen;
buf_element_t *buf;
+ xine_waveformatex wave;
+ uint32_t total_size = sizeof(xine_waveformatex) + sizeof(this->header) +
+ sizeof(uint32_t)*this->totalframes;
+ unsigned char *header;
+
+ header = malloc(total_size);
this->audio_fifo = this->stream->audio_fifo;
@@ -180,27 +186,43 @@ static void demux_tta_send_headers(demux_plugin_t *this_gen) {
/* send start buffers */
_x_demux_control_start(this->stream);
- /* send init info to decoders */
- if (this->audio_fifo) {
- xine_waveformatex wave;
-
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->type = BUF_AUDIO_TTA;
- buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
- buf->decoder_info[0] = 0;
- buf->decoder_info[1] = le2me_32(this->header.tta.samplerate);
- buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample);
- buf->decoder_info[3] = le2me_16(this->header.tta.channels);
+ /* create header */
+ wave.cbSize = total_size - sizeof(xine_waveformatex);
- buf->size = sizeof(xine_waveformatex) + sizeof(this->header) + sizeof(uint32_t)*this->totalframes;
- memcpy(buf->content+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header));
- memcpy(buf->content+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes);
+ memcpy(header, &wave, sizeof(wave));
+ memcpy(header+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header));
+ memcpy(header+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes);
- wave.cbSize = buf->size - sizeof(xine_waveformatex);
- memcpy(buf->content, &wave, sizeof(wave));
-
- this->audio_fifo->put (this->audio_fifo, buf);
+ /* send init info to decoders */
+ if (this->audio_fifo) {
+ uint32_t bytes_left = total_size;
+
+ /* We are sending the seektable as well, and this may be larger than
+ buf->max_size */
+ while (bytes_left) {
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER;
+ buf->type = BUF_AUDIO_TTA;
+
+ /* Copy min(bytes_left, max_size) bytes */
+ buf->size = bytes_left < buf->max_size ? bytes_left : buf->max_size;
+ memcpy(buf->content, header+(total_size-bytes_left), buf->size);
+
+ bytes_left -= buf->size;
+
+ /* The decoder information only needs the decoder information on the last
+ buffer element. */
+ if (!bytes_left) {
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
+ buf->decoder_info[0] = 0;
+ buf->decoder_info[1] = le2me_32(this->header.tta.samplerate);
+ buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample);
+ buf->decoder_info[3] = le2me_16(this->header.tta.channels);
+ }
+ this->audio_fifo->put (this->audio_fifo, buf);
+ }
}
+ free(header);
}
static int demux_tta_seek (demux_plugin_t *this_gen,
@@ -258,7 +280,7 @@ static int demux_tta_get_status (demux_plugin_t *this_gen) {
static int demux_tta_get_stream_length (demux_plugin_t *this_gen) {
demux_tta_t *this = (demux_tta_t *) this_gen;
- return (int)(FRAME_TIME * this->totalframes * 1000);
+ return le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate); /* milliseconds */
}
static uint32_t demux_tta_get_capabilities(demux_plugin_t *this_gen) {