summaryrefslogtreecommitdiff
path: root/src/libdts/xine_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdts/xine_decoder.c')
-rw-r--r--src/libdts/xine_decoder.c247
1 files changed, 161 insertions, 86 deletions
diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c
index 21258c114..78637119c 100644
--- a/src/libdts/xine_decoder.c
+++ b/src/libdts/xine_decoder.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2001 the xine project
+ * Copyright (C) 2000-2004 the xine project
*
* This file is part of xine, a unix video player.
*
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_decoder.c,v 1.47 2004/01/12 17:35:16 miguelfreitas Exp $
+ * $Id: xine_decoder.c,v 1.48 2004/04/09 14:57:26 mroi Exp $
*
* 04-09-2001 DTS passtrough (C) Joachim Koenig
* 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton
@@ -42,13 +42,31 @@
#include "xineutils.h"
#include "audio_out.h"
#include "buffer.h"
-#include "dts_debug.h"
-#include "decoder.h"
+#include "dts.h"
+
typedef struct {
audio_decoder_class_t decoder_class;
} dts_class_t;
+typedef struct {
+ audio_decoder_t audio_decoder;
+
+ xine_stream_t *stream;
+ audio_decoder_class_t *class;
+
+ dts_state_t *dts_state;
+
+ uint32_t rate;
+ uint32_t bits_per_sample;
+ uint32_t number_of_channels;
+
+ int output_open;
+
+ int bypass_mode;
+
+} dts_decoder_t;
+
static void dts_reset (audio_decoder_t *this_gen);
static void dts_discontinuity (audio_decoder_t *this_gen);
@@ -61,13 +79,31 @@ static void dts_reset (audio_decoder_t *this_gen) {
static void dts_discontinuity (audio_decoder_t *this_gen) {
}
+static inline int16_t blah (int32_t i) {
+
+ if (i > 0x43c07fff)
+ return 32767;
+ else if (i < 0x43bf8000)
+ return -32768;
+ else
+ return i - 0x43c00000;
+}
+
+static inline void float_to_int (float * _f, int16_t * s16, int num_channels) {
+ int i;
+ int32_t * f = (int32_t *) _f; /* XXX assumes IEEE float format */
+
+ for (i = 0; i < 256; i++) {
+ s16[num_channels*i] = blah (f[i]);
+ }
+}
+
static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
dts_decoder_t *this = (dts_decoder_t *) this_gen;
uint8_t *data_in = (uint8_t *)buf->content;
uint8_t *data_out;
audio_buffer_t *audio_buffer;
- uint32_t ac5_pcm_samples;
uint32_t ac5_spdif_type=0;
uint32_t ac5_length=0;
uint32_t ac5_pcm_length;
@@ -82,18 +118,6 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
dts_parse_data (this, buf);
#endif
- if ((this->stream->audio_out->get_capabilities(this->stream->audio_out) & AO_CAP_MODE_AC5) == 0) {
- return;
- }
- if (!this->output_open) {
- this->output_open = (this->stream->audio_out->open (this->stream->audio_out, this->stream,
- this->bits_per_sample,
- this->rate,
- AO_CAP_MODE_AC5));
- }
- if (!this->output_open)
- return;
-
if (buf->decoder_flags & BUF_FLAG_PREVIEW)
return;
@@ -110,100 +134,144 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
return;
}
- if ((data_in[0] != 0x7f) ||
- (data_in[1] != 0xfe) ||
- (data_in[2] != 0x80) ||
- (data_in[3] != 0x01)) {
+ {
+ int flags, sample_rate, bit_rate;
+
+ ac5_length = dts_syncinfo(this->dts_state, data_in, &flags, &sample_rate,
+ &bit_rate, &ac5_pcm_length);
+ }
+
+ if(!ac5_length) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: DTS Sync bad\n");
return;
}
audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out);
- audio_buffer->frame_header_count = buf->decoder_info[1]; /* Number of frames */
- audio_buffer->first_access_unit = buf->decoder_info[2]; /* First access unit */
-
-#ifdef LOG_DEBUG
- printf("libdts: DTS frame_header_count = %u\n",audio_buffer->frame_header_count);
- printf("libdts: DTS first access unit = %u\n",audio_buffer->first_access_unit);
-#endif
-
+
if (n == first_access_unit) {
audio_buffer->vpts = buf->pts;
} else {
audio_buffer->vpts = 0;
}
-
- data_out=(uint8_t *) audio_buffer->mem;
-
- ac5_pcm_samples=((data_in[4] & 0x01) << 6) | ((data_in[5] >>2) & 0x3f);
+
+ if(this->bypass_mode) {
+ if (!this->output_open) {
+ this->output_open = (this->stream->audio_out->open (this->stream->audio_out, this->stream,
+ this->bits_per_sample,
+ this->rate,
+ AO_CAP_MODE_AC5));
+ }
+
+ if (!this->output_open)
+ return;
+
+ audio_buffer->frame_header_count = buf->decoder_info[1]; /* Number of frames */
+ audio_buffer->first_access_unit = buf->decoder_info[2]; /* First access unit */
+#ifdef LOG_DEBUG
+ printf("libdts: DTS frame_header_count = %u\n",audio_buffer->frame_header_count);
+ printf("libdts: DTS first access unit = %u\n",audio_buffer->first_access_unit);
+#endif
- ac5_length=((data_in[5] & 0x03) << 12) | (data_in[6] << 4) | ((data_in[7] & 0xf0) >> 4);
- ac5_length++;
+ data_out=(uint8_t *) audio_buffer->mem;
- if (ac5_length > 8191) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: ac5_length too long\n");
- ac5_pcm_length = 0;
- } else {
- ac5_pcm_length = (ac5_pcm_samples + 1) * 32;
- }
+ if (ac5_length > 8191) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: ac5_length too long\n");
+ ac5_pcm_length = 0;
+ }
- switch (ac5_pcm_length) {
- case 512:
- ac5_spdif_type = 0x0b; /* DTS-1 (512-sample bursts) */
- break;
- case 1024:
- ac5_spdif_type = 0x0c; /* DTS-1 (1024-sample bursts) */
- break;
- case 2048:
- ac5_spdif_type = 0x0d; /* DTS-1 (2048-sample bursts) */
- break;
- default:
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "libdts: DTS %i-sample bursts not supported\n", ac5_pcm_length);
- return;
- }
+ switch (ac5_pcm_length) {
+ case 512:
+ ac5_spdif_type = 0x0b; /* DTS-1 (512-sample bursts) */
+ break;
+ case 1024:
+ ac5_spdif_type = 0x0c; /* DTS-1 (1024-sample bursts) */
+ break;
+ case 2048:
+ ac5_spdif_type = 0x0d; /* DTS-1 (2048-sample bursts) */
+ break;
+ default:
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "libdts: DTS %i-sample bursts not supported\n", ac5_pcm_length);
+ return;
+ }
#ifdef LOG_DEBUG
- {
- int i;
- printf("libdts: DTS frame type=%d\n",data_in[4] >> 7);
- printf("libdts: DTS deficit frame count=%d\n",(data_in[4] & 0x7f) >> 2);
- printf("libdts: DTS AC5 PCM samples=%d\n",ac5_pcm_samples);
- printf("libdts: DTS AC5 length=%d\n",ac5_length);
- printf("libdts: DTS AC5 bitrate=%d\n",((data_in[8] & 0x03) << 4) | (data_in[8] >> 4));
- printf("libdts: DTS AC5 spdif type=%d\n", ac5_spdif_type);
-
- printf("libdts: ");
- for(i=2000;i<2048;i++) {
- printf("%02x ",data_in[i]);
- }
- printf("\n");
- }
+ {
+ int i;
+ printf("libdts: DTS frame type=%d\n",data_in[4] >> 7);
+ printf("libdts: DTS deficit frame count=%d\n",(data_in[4] & 0x7f) >> 2);
+ printf("libdts: DTS AC5 PCM samples=%d\n",ac5_pcm_samples);
+ printf("libdts: DTS AC5 length=%d\n",ac5_length);
+ printf("libdts: DTS AC5 bitrate=%d\n",((data_in[8] & 0x03) << 4) | (data_in[8] >> 4));
+ printf("libdts: DTS AC5 spdif type=%d\n", ac5_spdif_type);
+
+ printf("libdts: ");
+ for(i=2000;i<2048;i++) {
+ printf("%02x ",data_in[i]);
+ }
+ printf("\n");
+ }
#endif
#ifdef LOG_DEBUG
- printf("libdts: DTS length=%d loop=%d pts=%lld\n",ac5_pcm_length,n,audio_buffer->vpts);
+ printf("libdts: DTS length=%d loop=%d pts=%lld\n",ac5_pcm_length,n,audio_buffer->vpts);
#endif
- audio_buffer->num_frames = ac5_pcm_length;
-
- data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */
- data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */
- data_out[4] = ac5_spdif_type; /* DTS data */
- data_out[5] = 0; /* Unknown */
- data_out[6] = (ac5_length << 3) & 0xff; /* ac5_length * 8 */
- data_out[7] = ((ac5_length ) >> 5) & 0xff;
-
- if( ac5_pcm_length ) {
- if( ac5_pcm_length % 2) {
- swab(data_in, &data_out[8], ac5_length );
- } else {
- swab(data_in, &data_out[8], ac5_length + 1);
+ audio_buffer->num_frames = ac5_pcm_length;
+
+ data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */
+ data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */
+ data_out[4] = ac5_spdif_type; /* DTS data */
+ data_out[5] = 0; /* Unknown */
+ data_out[6] = (ac5_length << 3) & 0xff; /* ac5_length * 8 */
+ data_out[7] = ((ac5_length ) >> 5) & 0xff;
+
+ if( ac5_pcm_length ) {
+ if( ac5_pcm_length % 2) {
+ swab(data_in, &data_out[8], ac5_length );
+ } else {
+ swab(data_in, &data_out[8], ac5_length + 1);
+ }
+ }
+ } else {
+ int i, flags = DTS_STEREO;
+ int16_t *int_samples = audio_buffer->mem;
+ level_t level = 1.0;
+ sample_t *samples = dts_samples(this->dts_state);
+
+ if (!this->output_open) {
+ this->output_open = (this->stream->audio_out->open (this->stream->audio_out, this->stream,
+ this->bits_per_sample,
+ this->rate,
+ AO_CAP_MODE_STEREO));
+ }
+
+ if (!this->output_open)
+ return;
+
+ if(dts_frame(this->dts_state, data_in, &flags, &level, 384)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: dts_frame error\n");
+ return;
+ }
+
+ for(i = 0; i < 2; i++) {
+ if(dts_block(this->dts_state)) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "libdts: dts_block error on audio channel %d\n", i);
+ audio_buffer->num_frames = 0;
+ }
+
+ float_to_int (&samples[0*256], int_samples+(i*256*2), 2);
+ float_to_int (&samples[1*256], int_samples+(i*256*2)+1, 2);
}
+
+ audio_buffer->num_frames = 256*2;
}
+
this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream);
+
}
}
@@ -229,6 +297,13 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre
this->audio_decoder.discontinuity = dts_discontinuity;
this->audio_decoder.dispose = dts_dispose;
+ this->dts_state = dts_init(0);
+
+ if(stream->audio_out->get_capabilities(stream->audio_out) & AO_CAP_MODE_AC5)
+ this->bypass_mode = 1;
+ else
+ this->bypass_mode = 0;
+
this->stream = stream;
this->class = class_gen;
this->output_open = 0;