summaryrefslogtreecommitdiff
path: root/src/libac3/xine_decoder.c
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-07-10 21:50:31 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-07-10 21:50:31 +0000
commitd8b2a2e6ab69169bab5ca40b69bfa5dac893bd0e (patch)
tree6d2879e005ef8db84801c81e52450ee8736c6454 /src/libac3/xine_decoder.c
parent4cc9fd313df701f722a81ad4bb551155415ce5cc (diff)
downloadxine-lib-d8b2a2e6ab69169bab5ca40b69bfa5dac893bd0e.tar.gz
xine-lib-d8b2a2e6ab69169bab5ca40b69bfa5dac893bd0e.tar.bz2
latest libac3 from walken
CVS patchset: 265 CVS date: 2001/07/10 21:50:31
Diffstat (limited to 'src/libac3/xine_decoder.c')
-rw-r--r--src/libac3/xine_decoder.c203
1 files changed, 167 insertions, 36 deletions
diff --git a/src/libac3/xine_decoder.c b/src/libac3/xine_decoder.c
index 46ac1b8a3..8249618f6 100644
--- a/src/libac3/xine_decoder.c
+++ b/src/libac3/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.10 2001/06/09 17:07:21 guenter Exp $
+ * $Id: xine_decoder.c,v 1.11 2001/07/10 21:50:31 guenter Exp $
*
* stuff needed to turn libac3 into a xine decoder plugin
*/
@@ -36,11 +36,14 @@
#include "audio_out.h"
#include "ac3.h"
+#include "ac3_internal.h"
#include "buffer.h"
#include "xine_internal.h"
#define FRAME_SIZE 4096
+stream_samples_t samples;
+
/* int ac3file; */
typedef struct ac3dec_decoder_s {
@@ -54,10 +57,20 @@ typedef struct ac3dec_decoder_s {
int frame_length, frame_todo;
uint16_t syncword;
+ ac3_state_t ac3_state;
+ int ac3_flags;
+ int ac3_bit_rate;
+ int ac3_sample_rate;
+ float ac3_level;
+
+ int ac3_flags_map[8];
+ int ao_flags_map[8];
+
+ int16_t samples [6 * 6 * 256];
+
ao_functions_t *audio_out;
int audio_caps;
int bypass_mode;
- int max_num_channels;
int output_sampling_rate;
int output_open;
int output_mode;
@@ -72,6 +85,7 @@ int ac3dec_can_handle (audio_decoder_t *this_gen, int buf_type) {
void ac3dec_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
ac3dec_decoder_t *this = (ac3dec_decoder_t *) this_gen;
+ /* int i; */
this->audio_out = audio_out;
this->audio_caps = audio_out->get_capabilities(audio_out);
@@ -91,31 +105,94 @@ void ac3dec_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
else {
this->bypass_mode = 0;
+ this->ac3_flags_map[AC3_MONO] = AC3_MONO;
+ this->ac3_flags_map[AC3_STEREO] = AC3_STEREO;
+ this->ac3_flags_map[AC3_3F] = AC3_STEREO;
+ this->ac3_flags_map[AC3_2F1R] = AC3_STEREO;
+ this->ac3_flags_map[AC3_3F1R] = AC3_STEREO;
+ this->ac3_flags_map[AC3_2F2R] = AC3_STEREO;
+ this->ac3_flags_map[AC3_3F2R] = AC3_STEREO;
+
+ this->ao_flags_map[AC3_MONO] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_STEREO] = AO_CAP_MODE_STEREO;
+ this->ao_flags_map[AC3_3F] = AO_CAP_MODE_STEREO;
+ this->ao_flags_map[AC3_2F1R] = AO_CAP_MODE_STEREO;
+ this->ao_flags_map[AC3_3F1R] = AO_CAP_MODE_STEREO;
+ this->ao_flags_map[AC3_2F2R] = AO_CAP_MODE_STEREO;
+ this->ao_flags_map[AC3_3F2R] = AO_CAP_MODE_STEREO;
+
/* find best mode */
- if (this->audio_caps & AO_CAP_MODE_5CHANNEL)
- this->max_num_channels = 5;
- else if (this->audio_caps & AO_CAP_MODE_4CHANNEL)
- this->max_num_channels = 4;
- else if (this->audio_caps & AO_CAP_MODE_STEREO)
- this->max_num_channels = 2;
- else {
+ if (this->audio_caps & AO_CAP_MODE_5CHANNEL) {
+
+ this->ac3_flags_map[AC3_2F2R] = AC3_2F2R;
+ this->ac3_flags_map[AC3_3F2R] = AC3_3F2R;
+ this->ao_flags_map[AC3_2F2R] = AO_CAP_MODE_4CHANNEL;
+ this->ao_flags_map[AC3_3F2R] = AO_CAP_MODE_5CHANNEL;
+
+ } else if (this->audio_caps & AO_CAP_MODE_4CHANNEL) {
+
+ this->ac3_flags_map[AC3_2F2R] = AC3_2F2R;
+ this->ac3_flags_map[AC3_3F2R] = AC3_2F2R;
+
+ this->ao_flags_map[AC3_2F2R] = AO_CAP_MODE_4CHANNEL;
+ this->ao_flags_map[AC3_3F2R] = AO_CAP_MODE_4CHANNEL;
+
+ /* else if (this->audio_caps & AO_CAP_MODE_STEREO)
+ defaults are ok */
+ } else {
printf ("HELP! a mono-only audio driver?!\n");
- this->max_num_channels = 1;
+
+ this->ac3_flags_map[AC3_MONO] = AC3_MONO;
+ this->ac3_flags_map[AC3_STEREO] = AC3_MONO;
+ this->ac3_flags_map[AC3_3F] = AC3_MONO;
+ this->ac3_flags_map[AC3_2F1R] = AC3_MONO;
+ this->ac3_flags_map[AC3_3F1R] = AC3_MONO;
+ this->ac3_flags_map[AC3_2F2R] = AC3_MONO;
+ this->ac3_flags_map[AC3_3F2R] = AC3_MONO;
+
+ this->ao_flags_map[AC3_MONO] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_STEREO] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_3F] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_2F1R] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_3F1R] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_2F2R] = AO_CAP_MODE_MONO;
+ this->ao_flags_map[AC3_3F2R] = AO_CAP_MODE_MONO;
}
}
+ /*
+ for (i = 0; i<8; i++)
+ this->ac3_flags_map[i] |= AC3_ADJUST_LEVEL;
+*/
/* ac3file = open ("test.ac3", O_CREAT); */
}
+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]);
+ }
+}
+
void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
ac3dec_decoder_t *this = (ac3dec_decoder_t *) this_gen;
uint8_t *current = buf->content;
uint8_t *end = buf->content + buf->size;
- ac3_frame_t *ac3_frame=NULL;
-/* int sampling_rate; */
int output_mode = AO_CAP_MODE_STEREO;
uint8_t byte;
@@ -123,7 +200,8 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
if (buf->decoder_info[0] == 0)
return;
- this->pts = buf->PTS;
+ if (buf->PTS)
+ this->pts = buf->PTS;
while (current != end) {
@@ -144,7 +222,7 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
this->frame_buffer[0] = 0x0b;
this->frame_buffer[1] = 0x77;
- this->sync_todo = 4;
+ this->sync_todo = 5;
this->frame_ptr = this->frame_buffer+2;
}
} else {
@@ -152,8 +230,12 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
this->sync_todo--;
if (this->sync_todo==0) {
- this->frame_length = ac3_frame_length (this->frame_buffer);
- this->frame_todo = this->frame_length - 6;
+
+ this->frame_length = ac3_syncinfo (this->frame_buffer,
+ &this->ac3_flags,
+ &this->ac3_sample_rate,
+ &this->ac3_bit_rate);
+ this->frame_todo = this->frame_length - 7;
}
}
@@ -175,33 +257,69 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
*/
if (!this->bypass_mode) {
+
+ int ac3_output_flags, i;
+ float level = this->ac3_level;
/* oki, decode this frame in software*/
/* write (ac3file, this->frame_buffer, this->frame_length); */
- ac3_frame = ac3_decode_frame (this->frame_buffer, this->max_num_channels);
-
/* determine output mode */
- switch (ac3_frame->num_channels) {
- case 1:
- output_mode = AO_CAP_MODE_MONO;
- break;
- case 2:
- output_mode = AO_CAP_MODE_STEREO;
- break;
- case 4:
- output_mode = AO_CAP_MODE_4CHANNEL;
- break;
- case 5:
- output_mode = AO_CAP_MODE_5CHANNEL;
- break;
+
+ ac3_output_flags = this->ac3_flags_map[this->ac3_flags & AC3_CHANNEL_MASK];
+
+ if (ac3_frame (&this->ac3_state,
+ this->frame_buffer,
+ &ac3_output_flags,
+ &level, 384)) {
+ printf ("libac3: ac3_frame error\n");
+ goto error;
}
+ output_mode = this->ao_flags_map[ac3_output_flags];
+
+ /*
+ * decode ac3 and convert/interleave samples
+ */
+
+ for (i = 0; i < 6; i++) {
+ if (ac3_block (&this->ac3_state)) {
+ printf ("libac3: ac3_block error\n");
+ goto error;
+ }
+
+ switch (output_mode) {
+ case AO_CAP_MODE_MONO:
+ float_to_int (*samples, this->samples+i*256, 1);
+ break;
+ case AO_CAP_MODE_STEREO:
+ float_to_int (samples[0], this->samples+i*256*2, 2);
+ float_to_int (samples[1], this->samples+1+i*256*2, 2);
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ float_to_int (samples[0], this->samples+i*256*4, 4);
+ float_to_int (samples[1], this->samples+1+i*256*4, 4);
+ float_to_int (samples[2], this->samples+2+i*256*4, 4);
+ float_to_int (samples[3], this->samples+3+i*256*4, 4);
+ break;
+ case AO_CAP_MODE_5CHANNEL:
+ float_to_int (samples[0], this->samples+i*256*5, 5);
+ float_to_int (samples[1], this->samples+1+i*256*5, 5);
+ float_to_int (samples[2], this->samples+2+i*256*5, 5);
+ float_to_int (samples[3], this->samples+3+i*256*5, 5);
+ float_to_int (samples[4], this->samples+4+i*256*5, 5);
+ break;
+ default:
+ printf ("libac3: help - unsupported mode %08x\n", output_mode);
+ }
+ }
+
+
/* output decoded samples */
if (!this->output_open
- || (ac3_frame->sampling_rate != this->output_sampling_rate)
+ || (this->ac3_sample_rate != this->output_sampling_rate)
|| (output_mode != this->output_mode)) {
if (this->output_open)
@@ -209,19 +327,23 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
this->output_open = (this->audio_out->open (this->audio_out, 16,
- ac3_frame->sampling_rate,
+ this->ac3_sample_rate,
output_mode) == 1);
- this->output_sampling_rate = ac3_frame->sampling_rate;
+ this->output_sampling_rate = this->ac3_sample_rate;
this->output_mode = output_mode;
}
if (this->output_open) {
+
this->audio_out->write_audio_data (this->audio_out,
- ac3_frame->audio_data,
+ this->samples,
256*6,
this->pts);
this->pts = 0;
}
+
+ error:
+
} else {
/*
@@ -229,8 +351,13 @@ void ac3dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
*/
if (!this->output_open) {
+
+ int sample_rate, bit_rate, flags;
+
+ ac3_syncinfo (this->frame_buffer, &flags, &sample_rate, &bit_rate);
+
this->output_open = (this->audio_out->open (this->audio_out, 16,
- ac3_sampling_rate(this->frame_buffer),
+ sample_rate,
AO_CAP_MODE_AC3) == 1);
this->output_mode = AO_CAP_MODE_AC3;
}
@@ -261,6 +388,8 @@ void ac3dec_close (audio_decoder_t *this_gen) {
if (this->output_open)
this->audio_out->close (this->audio_out);
+ this->output_open = 0;
+
/* close (ac3file); */
}
@@ -283,6 +412,8 @@ audio_decoder_t *init_audio_decoder_plugin (int iface_version, config_values_t *
this->audio_decoder.decode_data = ac3dec_decode_data;
this->audio_decoder.close = ac3dec_close;
this->audio_decoder.get_identifier = ac3dec_get_id;
+
+ this->ac3_level = (float) cfg->lookup_int (cfg, "ac3_level", 100) / 100.0;
return (audio_decoder_t *) this;
}