diff options
-rw-r--r-- | src/libdts/xine_decoder.c | 245 |
1 files changed, 202 insertions, 43 deletions
diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c index e38591bb1..82df201ef 100644 --- a/src/libdts/xine_decoder.c +++ b/src/libdts/xine_decoder.c @@ -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.50 2004/05/18 20:38:28 jcdutton Exp $ + * $Id: xine_decoder.c,v 1.51 2004/05/19 18:00:47 jcdutton Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton @@ -61,7 +61,7 @@ typedef struct { audio_decoder_class_t *class; dts_state_t *dts_state; - + int audio_caps; uint32_t rate; uint32_t bits_per_sample; uint32_t number_of_channels; @@ -69,9 +69,12 @@ typedef struct { int output_open; int bypass_mode; - int decoder_flags; - int decoder_sample_rate; - int decoder_bit_rate; + int dts_flags; + int dts_sample_rate; + int dts_bit_rate; + int dts_flags_map[11]; /* Convert from stream dts_flags to the dts_flags we want from the dts downmixer */ + int ao_flags_map[11]; /* Convert from the xine AO_CAP's to dts_flags. */ + int have_lfe; } dts_decoder_t; @@ -88,6 +91,7 @@ static void dts_reset (audio_decoder_t *this_gen) { static void dts_discontinuity (audio_decoder_t *this_gen) { } +#if 0 static inline int16_t blah (int32_t i) { if (i > 0x43c07fff) @@ -97,7 +101,6 @@ static inline int16_t blah (int32_t i) { 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 */ @@ -106,6 +109,28 @@ static inline void float_to_int (float * _f, int16_t * s16, int num_channels) { s16[num_channels*i] = blah (f[i]); } } +#endif + +static inline void float_to_int (float * _f, int16_t * s16, int num_channels) { + int i; + float f; + for (i = 0; i < 256; i++) { + f = _f[i] * 32767; + if (f > INT16_MAX) f = INT16_MAX; + if (f < INT16_MIN) f = INT16_MIN; + s16[num_channels*i] = f; + /* printf("samples[%d] = %f, %d\n", i, _f[i], s16[num_channels*i]); */ + } +} + + +static inline void mute_channel (int16_t * s16, int num_channels) { + int i; + + for (i = 0; i < 256; i++) { + s16[num_channels*i] = 0; + } +} static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { @@ -118,9 +143,10 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { uint32_t ac5_pcm_length; uint32_t number_of_frames; uint32_t first_access_unit; - int old_decoder_flags; - int old_decoder_sample_rate; - int old_decoder_bit_rate; + int old_dts_flags; + int old_dts_sample_rate; + int old_dts_bit_rate; + int output_mode = AO_CAP_MODE_STEREO; int n; lprintf("decode_data\n"); @@ -140,25 +166,25 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: DTS length error\n"); return; } - old_decoder_flags = this->decoder_flags; - old_decoder_sample_rate = this->decoder_sample_rate; - old_decoder_bit_rate = this->decoder_bit_rate; - - ac5_length = dts_syncinfo(this->dts_state, data_in, &this->decoder_flags, &this->decoder_sample_rate, - &this->decoder_bit_rate, &ac5_pcm_length); - + old_dts_flags = this->dts_flags; + old_dts_sample_rate = this->dts_sample_rate; + old_dts_bit_rate = this->dts_bit_rate; + + ac5_length = dts_syncinfo(this->dts_state, data_in, &this->dts_flags, &this->dts_sample_rate, + &this->dts_bit_rate, &ac5_pcm_length); + if(!ac5_length) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: DTS Sync bad\n"); return; } if (!_x_meta_info_get(this->stream, XINE_META_INFO_AUDIOCODEC) || - old_decoder_flags != this->decoder_flags || - old_decoder_sample_rate != this->decoder_sample_rate || - old_decoder_bit_rate != this->decoder_bit_rate) { + old_dts_flags != this->dts_flags || + old_dts_sample_rate != this->dts_sample_rate || + old_dts_bit_rate != this->dts_bit_rate) { _x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC, "DTS"); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->decoder_bit_rate); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, this->decoder_sample_rate); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->dts_bit_rate); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, this->dts_sample_rate); } @@ -169,8 +195,9 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } else { audio_buffer->vpts = 0; } - + if(this->bypass_mode) { + /* SPDIF digital output */ if (!this->output_open) { this->output_open = (this->stream->audio_out->open (this->stream->audio_out, this->stream, this->bits_per_sample, @@ -248,38 +275,100 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } } } else { - int i, flags = DTS_STEREO; + /* Software decode */ + int i, dts_flags; int16_t *int_samples = audio_buffer->mem; + int number_of_dts_blocks; + level_t level = 1.0; - sample_t *samples = dts_samples(this->dts_state); - - if (!this->output_open) { + sample_t *samples; + + this->have_lfe = this->dts_flags & DTS_LFE; + dts_flags = this->dts_flags_map[this->dts_flags & DTS_CHANNEL_MASK]; + if (this->have_lfe) + if (this->audio_caps & AO_CAP_MODE_5_1CHANNEL) { + output_mode = AO_CAP_MODE_5_1CHANNEL; + dts_flags |= DTS_LFE; + } else if (this->audio_caps & AO_CAP_MODE_4_1CHANNEL) { + output_mode = AO_CAP_MODE_4_1CHANNEL; + dts_flags |= DTS_LFE; + } else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "liba52: WHAT DO I DO!!!\n"); + output_mode = this->ao_flags_map[dts_flags & DTS_CHANNEL_MASK]; + } + else + output_mode = this->ao_flags_map[dts_flags & DTS_CHANNEL_MASK]; + + if(dts_frame(this->dts_state, data_in, &dts_flags, &level, 0)) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: dts_frame error\n"); + 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_STEREO)); + output_mode)); } 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++) { + number_of_dts_blocks = dts_blocks_num (this->dts_state); + audio_buffer->num_frames = 256*number_of_dts_blocks; + for(i = 0; i < number_of_dts_blocks; 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; + break; + } + + samples = dts_samples(this->dts_state); + switch (output_mode) { + case AO_CAP_MODE_MONO: + float_to_int (&samples[0], int_samples+(i*256), 1); + break; + case AO_CAP_MODE_STEREO: + /* Tested, working. */ + 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); + break; + case AO_CAP_MODE_4CHANNEL: + /* Tested, Only Rear channel output */ + printf("4 channel samples start %d\n", i); + float_to_int (&samples[0*256], int_samples+(i*256*4), 4); /* L? */ + float_to_int (&samples[1*256], int_samples+(i*256*4)+1, 4); /* R? */ + float_to_int (&samples[2*256], int_samples+(i*256*4)+2, 4); /* RL? */ + float_to_int (&samples[3*256], int_samples+(i*256*4)+3, 4); /* RR? */ + break; + case AO_CAP_MODE_4_1CHANNEL: + /* Tested, not working */ + float_to_int (&samples[0*256], int_samples+(i*256*6)+4, 6); /* LFE? */ + float_to_int (&samples[1*256], int_samples+(i*256*6)+0, 6); /* L? */ + float_to_int (&samples[2*256], int_samples+(i*256*6)+1, 6); /* R? */ + float_to_int (&samples[3*256], int_samples+(i*256*6)+2, 6); /* RL? */ + float_to_int (&samples[4*256], int_samples+(i*256*6)+3, 6); /* RR? */ + mute_channel ( int_samples+(i*256*6)+4, 6); /* C */ + break; + case AO_CAP_MODE_5CHANNEL: + float_to_int (&samples[0*256], int_samples+(i*256*6)+4, 6); /* C */ + float_to_int (&samples[1*256], int_samples+(i*256*6)+0, 6); /* L */ + float_to_int (&samples[2*256], int_samples+(i*256*6)+1, 6); /* R */ + float_to_int (&samples[3*256], int_samples+(i*256*6)+2, 6); /* RL */ + float_to_int (&samples[4*256], int_samples+(i*256*6)+3, 6); /* RR */ + mute_channel ( int_samples+(i*256*6)+5, 6); /* LFE */ + break; + case AO_CAP_MODE_5_1CHANNEL: + float_to_int (&samples[0*256], int_samples+(i*256*6)+4, 6); /* C */ + float_to_int (&samples[1*256], int_samples+(i*256*6)+0, 6); /* L */ + float_to_int (&samples[2*256], int_samples+(i*256*6)+1, 6); /* R */ + float_to_int (&samples[3*256], int_samples+(i*256*6)+2, 6); /* RL */ + float_to_int (&samples[4*256], int_samples+(i*256*6)+3, 6); /* RR */ + float_to_int (&samples[5*256], int_samples+(i*256*6)+5, 6); /* LFE */ /* Not working yet */ + break; + default: + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "liba52: help - unsupported mode %08x\n", output_mode); } - - 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); @@ -310,12 +399,82 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre 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->audio_caps = stream->audio_out->get_capabilities(stream->audio_out); + if(this->audio_caps & AO_CAP_MODE_AC5) this->bypass_mode = 1; - else + else { this->bypass_mode = 0; - + /* FIXME: Leave "DOLBY pro logic" downmix out for now. */ + + this->dts_flags_map[DTS_MONO] = DTS_MONO; + this->dts_flags_map[DTS_STEREO] = DTS_STEREO; + this->dts_flags_map[DTS_3F] = DTS_STEREO; + this->dts_flags_map[DTS_2F1R] = DTS_STEREO; + this->dts_flags_map[DTS_3F1R] = DTS_STEREO; + this->dts_flags_map[DTS_2F2R] = DTS_STEREO; + this->dts_flags_map[DTS_3F2R] = DTS_STEREO; + + this->ao_flags_map[DTS_MONO] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_STEREO] = AO_CAP_MODE_STEREO; + this->ao_flags_map[DTS_3F] = AO_CAP_MODE_STEREO; + this->ao_flags_map[DTS_2F1R] = AO_CAP_MODE_STEREO; + this->ao_flags_map[DTS_3F1R] = AO_CAP_MODE_STEREO; + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_STEREO; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_STEREO; + + /* find best mode */ + if (this->audio_caps & AO_CAP_MODE_5_1CHANNEL) { + + this->dts_flags_map[DTS_2F2R] = DTS_2F2R; + this->dts_flags_map[DTS_3F2R] = DTS_3F2R | DTS_LFE; + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_4CHANNEL; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_5CHANNEL; + + } else if (this->audio_caps & AO_CAP_MODE_5CHANNEL) { + + this->dts_flags_map[DTS_2F2R] = DTS_2F2R; + this->dts_flags_map[DTS_3F2R] = DTS_3F2R; + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_4CHANNEL; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_5CHANNEL; + + } else if (this->audio_caps & AO_CAP_MODE_4_1CHANNEL) { + + this->dts_flags_map[DTS_2F2R] = DTS_2F2R; + this->dts_flags_map[DTS_3F2R] = DTS_2F2R | DTS_LFE; + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_4CHANNEL; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_4CHANNEL; + + } else if (this->audio_caps & AO_CAP_MODE_4CHANNEL) { + + this->dts_flags_map[DTS_2F2R] = DTS_2F2R; + this->dts_flags_map[DTS_3F2R] = DTS_2F2R; + + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_4CHANNEL; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_4CHANNEL; + + /* else if (this->audio_caps & AO_CAP_MODE_STEREO) + defaults are ok */ + } else if (!(this->audio_caps & AO_CAP_MODE_STEREO)) { + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("HELP! a mono-only audio driver?!\n")); + + this->dts_flags_map[DTS_MONO] = DTS_MONO; + this->dts_flags_map[DTS_STEREO] = DTS_MONO; + this->dts_flags_map[DTS_3F] = DTS_MONO; + this->dts_flags_map[DTS_2F1R] = DTS_MONO; + this->dts_flags_map[DTS_3F1R] = DTS_MONO; + this->dts_flags_map[DTS_2F2R] = DTS_MONO; + this->dts_flags_map[DTS_3F2R] = DTS_MONO; + + this->ao_flags_map[DTS_MONO] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_STEREO] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_3F] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_2F1R] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_3F1R] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_MONO; + this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_MONO; + } + } + this->stream = stream; this->class = class_gen; this->output_open = 0; |