From 7e0416720dbeb41dec90ccb80428e5aa560e1a65 Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 9 Dec 2001 18:31:01 +0000 Subject: Move SPDIF encaps into the audio decoders. This makes the SPDIF out code in xine-engine/audio_out.c very simple. It will also make audio sync better as the correct number of samples will be passed to got_audio_samples. CVS patchset: 1195 CVS date: 2001/12/09 18:31:01 --- src/liba52/xine_decoder.c | 82 ++++++++++++++++++++++++-- src/libdts/xine_decoder.c | 100 +++++++++++++++++++++++--------- src/xine-engine/audio_out.c | 137 +------------------------------------------- 3 files changed, 151 insertions(+), 168 deletions(-) diff --git a/src/liba52/xine_decoder.c b/src/liba52/xine_decoder.c index 1c8da9e74..4fc3de135 100644 --- a/src/liba52/xine_decoder.c +++ b/src/liba52/xine_decoder.c @@ -17,11 +17,14 @@ * 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.12 2001/11/20 01:43:30 guenter Exp $ + * $Id: xine_decoder.c,v 1.13 2001/12/09 18:31:01 jcdutton Exp $ * * stuff needed to turn liba52 into a xine decoder plugin */ +/* required for swab() */ +#define _XOPEN_SOURCE 500 + #include #include @@ -77,6 +80,54 @@ typedef struct a52dec_decoder_s { int enable_surround_downmix; } a52dec_decoder_t; +struct frmsize_s +{ + uint16_t bit_rate; + uint16_t frm_size[3]; +}; + +static const struct frmsize_s frmsizecod_tbl[64] = +{ + { 32 ,{64 ,69 ,96 } }, + { 32 ,{64 ,70 ,96 } }, + { 40 ,{80 ,87 ,120 } }, + { 40 ,{80 ,88 ,120 } }, + { 48 ,{96 ,104 ,144 } }, + { 48 ,{96 ,105 ,144 } }, + { 56 ,{112 ,121 ,168 } }, + { 56 ,{112 ,122 ,168 } }, + { 64 ,{128 ,139 ,192 } }, + { 64 ,{128 ,140 ,192 } }, + { 80 ,{160 ,174 ,240 } }, + { 80 ,{160 ,175 ,240 } }, + { 96 ,{192 ,208 ,288 } }, + { 96 ,{192 ,209 ,288 } }, + { 112 ,{224 ,243 ,336 } }, + { 112 ,{224 ,244 ,336 } }, + { 128 ,{256 ,278 ,384 } }, + { 128 ,{256 ,279 ,384 } }, + { 160 ,{320 ,348 ,480 } }, + { 160 ,{320 ,349 ,480 } }, + { 192 ,{384 ,417 ,576 } }, + { 192 ,{384 ,418 ,576 } }, + { 224 ,{448 ,487 ,672 } }, + { 224 ,{448 ,488 ,672 } }, + { 256 ,{512 ,557 ,768 } }, + { 256 ,{512 ,558 ,768 } }, + { 320 ,{640 ,696 ,960 } }, + { 320 ,{640 ,697 ,960 } }, + { 384 ,{768 ,835 ,1152 } }, + { 384 ,{768 ,836 ,1152 } }, + { 448 ,{896 ,975 ,1344 } }, + { 448 ,{896 ,976 ,1344 } }, + { 512 ,{1024 ,1114 ,1536 } }, + { 512 ,{1024 ,1115 ,1536 } }, + { 576 ,{1152 ,1253 ,1728 } }, + { 576 ,{1152 ,1254 ,1728 } }, + { 640 ,{1280 ,1393 ,1920 } }, + { 640 ,{1280 ,1394 ,1920 } } +}; + int a52dec_can_handle (audio_decoder_t *this_gen, int buf_type) { return ((buf_type & 0xFFFF0000) == BUF_AUDIO_A52) ; } @@ -342,12 +393,31 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, uint32_t pts, uint32_t } if (this->output_open) { - + /* SPDIF Passthrough + * Build SPDIF Header and encaps the A52 audio data in it. + */ + uint32_t syncword, crc1, fscod,frmsizecod,bsid,bsmod,frame_size; + uint8_t *data_out,*data_in; audio_buffer_t *buf = this->audio_out->get_buffer (this->audio_out); - - memcpy (buf->mem, this->frame_buffer, this->frame_length); - - buf->num_frames = this->frame_length; + data_in=(uint8_t *) this->frame_buffer; + data_out=(uint8_t *) buf->mem; + syncword = data_in[0] | (data_in[1] << 8); + crc1 = data_in[2] | (data_in[3] << 8); + fscod = (data_in[4] >> 6) & 0x3; + frmsizecod = data_in[4] & 0x3f; + bsid = (data_in[5] >> 3) & 0x1f; + bsmod = data_in[5] & 0x7; // bsmod, stream = 0 + frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] ; + + data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ + data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ + data_out[4] = 0x01; /* AC3 data */ + data_out[5] = bsmod; /* bsmod, stream = 0 */ + data_out[6] = (frame_size << 4) & 0xff; /* frame_size * 16 */ + data_out[7] = ((frame_size ) >> 4) & 0xff; + swab(data_in, &data_out[8], frame_size * 2 ); + + buf->num_frames = 1536; buf->vpts = pts; buf->scr = scr; diff --git a/src/libdts/xine_decoder.c b/src/libdts/xine_decoder.c index 3d6c7801a..7ae35ba00 100644 --- a/src/libdts/xine_decoder.c +++ b/src/libdts/xine_decoder.c @@ -17,12 +17,15 @@ * 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.7 2001/11/28 23:43:14 jcdutton Exp $ + * $Id: xine_decoder.c,v 1.8 2001/12/09 18:31:02 jcdutton Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig + * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton * */ +/* required for swab() */ +#define _XOPEN_SOURCE 500 #include #include @@ -71,26 +74,60 @@ void dts_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) { 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=(uint8_t *)buf->content; + uint8_t *data_in = (uint8_t *)buf->content; + uint8_t *data_out; audio_buffer_t *audio_buffer; uint32_t ac5_type; + uint32_t ac5_spdif_type; uint32_t ac5_length; + uint32_t ac5_pcm_length; int i; if ((this->audio_caps & AO_CAP_MODE_AC5) == 0) { return; } - if ((data[0] != 0x7f) || - (data[1] != 0xfe) || - (data[2] != 0x80) || - (data[3] != 0x01)) { + if (!this->output_open) { + this->output_open = (this->audio_out->open (this->audio_out, this->bits_per_sample, + this->rate, + AO_CAP_MODE_AC5)); + } + if (!this->output_open) + return; + + audio_buffer = this->audio_out->get_buffer (this->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 */ + audio_buffer->vpts = buf->PTS; + audio_buffer->scr = buf->SCR; + + data_out=(uint8_t *) audio_buffer->mem; + + if ((data_in[0] != 0x7f) || + (data_in[1] != 0xfe) || + (data_in[2] != 0x80) || + (data_in[3] != 0x01)) { printf("DTS Sync bad\n"); return; } - ac5_type=((data[4] & 0x01) << 6) | ((data[5] >>2) & 0x3f); - ac5_length=((data[5] & 0x03) << 12) | ((data[6] & 0xff) << 4) | ((data[7] & 0xf0) >> 4); + ac5_type=((data_in[4] & 0x01) << 6) | ((data_in[5] >>2) & 0x3f); + ac5_length=((data_in[5] & 0x03) << 12) | ((data_in[6] & 0xff) << 4) | ((data_in[7] & 0xf0) >> 4); ac5_length++; ac5_length*=buf->decoder_info[1]; /* Number of frames */ + switch(ac5_type) { + case 0x0f: + ac5_spdif_type = 0x000b; /* DTS */ + break; + case 0x1f: + ac5_spdif_type = 0x000c; /* DTS */ + break; + case 0x3f: + ac5_spdif_type = 0x000d; /* DTS */ + break; + default: + ac5_spdif_type = 0x0000; /* DTS */ + break; + } /* printf("DTS AC5 length=%d\n",ac5_length); */ /* @@ -104,27 +141,36 @@ void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { printf("ac5_length too long\n"); return; } - - - if (!this->output_open) { - this->output_open = (this->audio_out->open (this->audio_out, this->bits_per_sample, - this->rate, - AO_CAP_MODE_AC5)); + + if (ac5_length <= 248) { + ac5_pcm_length = 64; + } else if (ac5_length <= 504) { + ac5_pcm_length = 128; + } else if (ac5_length <= 1016) { + ac5_pcm_length = 256; + } else if (ac5_length <= 2040) { + ac5_pcm_length = 512; + } else if (ac5_length <= 4088) { + ac5_pcm_length = 1024; + } else { + printf("BAD AC5 length\n"); + ac5_pcm_length = 512; } - if (!this->output_open) - return; - - audio_buffer = this->audio_out->get_buffer (this->audio_out); - memcpy (audio_buffer->mem, data, ac5_length); - - audio_buffer->frame_header_count = buf->decoder_info[1]; /* Number of frames */ - audio_buffer->first_access_unit = buf->decoder_info[2]; /* First access unit */ - audio_buffer->vpts = buf->PTS; - audio_buffer->scr = buf->SCR; - audio_buffer->num_frames = ac5_length / 2; - + if (ac5_pcm_length < (512 * audio_buffer->frame_header_count)) { + ac5_pcm_length = 512 * audio_buffer->frame_header_count ; + } + printf("DTS length=%d\n",ac5_pcm_length); + 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; + swab(data_in, &data_out[8], ac5_length ); + this->audio_out->put_buffer (this->audio_out, audio_buffer); - } void dts_close (audio_decoder_t *this_gen) { diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index abaf1b7df..ba112d0a6 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -17,7 +17,7 @@ * along with self program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: audio_out.c,v 1.36 2001/11/27 00:00:35 jcdutton Exp $ + * $Id: audio_out.c,v 1.37 2001/12/09 18:31:02 jcdutton Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe @@ -75,55 +75,6 @@ #define ZERO_BUF_SIZE 5000 -struct frmsize_s -{ - uint16_t bit_rate; - uint16_t frm_size[3]; -}; - - -static const struct frmsize_s frmsizecod_tbl[64] = -{ - { 32 ,{64 ,69 ,96 } }, - { 32 ,{64 ,70 ,96 } }, - { 40 ,{80 ,87 ,120 } }, - { 40 ,{80 ,88 ,120 } }, - { 48 ,{96 ,104 ,144 } }, - { 48 ,{96 ,105 ,144 } }, - { 56 ,{112 ,121 ,168 } }, - { 56 ,{112 ,122 ,168 } }, - { 64 ,{128 ,139 ,192 } }, - { 64 ,{128 ,140 ,192 } }, - { 80 ,{160 ,174 ,240 } }, - { 80 ,{160 ,175 ,240 } }, - { 96 ,{192 ,208 ,288 } }, - { 96 ,{192 ,209 ,288 } }, - { 112 ,{224 ,243 ,336 } }, - { 112 ,{224 ,244 ,336 } }, - { 128 ,{256 ,278 ,384 } }, - { 128 ,{256 ,279 ,384 } }, - { 160 ,{320 ,348 ,480 } }, - { 160 ,{320 ,349 ,480 } }, - { 192 ,{384 ,417 ,576 } }, - { 192 ,{384 ,418 ,576 } }, - { 224 ,{448 ,487 ,672 } }, - { 224 ,{448 ,488 ,672 } }, - { 256 ,{512 ,557 ,768 } }, - { 256 ,{512 ,558 ,768 } }, - { 320 ,{640 ,696 ,960 } }, - { 320 ,{640 ,697 ,960 } }, - { 384 ,{768 ,835 ,1152 } }, - { 384 ,{768 ,836 ,1152 } }, - { 448 ,{896 ,975 ,1344 } }, - { 448 ,{896 ,976 ,1344 } }, - { 512 ,{1024 ,1114 ,1536 } }, - { 512 ,{1024 ,1115 ,1536 } }, - { 576 ,{1152 ,1253 ,1728 } }, - { 576 ,{1152 ,1254 ,1728 } }, - { 640 ,{1280 ,1393 ,1920 } }, - { 640 ,{1280 ,1394 ,1920 } } -}; - struct audio_fifo_s { audio_buffer_t *first; audio_buffer_t *last; @@ -284,15 +235,9 @@ static void *ao_loop (void *this_gen) { audio_buffer_t *buf; int32_t gap; int delay; - int frame_size; - int fscod; - int frmsizecod; uint8_t *data; uint32_t cur_time; int num_output_frames ; - uint32_t ac5_type; - uint32_t ac5_length; - uint32_t ac5_pcm_length; int paused_wait; this->audio_loop_running = 1; @@ -420,86 +365,8 @@ static void *ao_loop (void *this_gen) { this->driver->write(this->driver, this->frame_buffer, num_output_frames); break; case AO_CAP_MODE_A52: - - this->frame_buffer[0] = 0xf872; /* spdif syncword */ - this->frame_buffer[1] = 0x4e1f; /* ............. */ - this->frame_buffer[2] = 0x0001; /* AC3 data */ - - data = (uint8_t *)&buf->mem[1]; /* skip AC3 sync */ - fscod = (data[2] >> 6) & 0x3; - frmsizecod = data[2] & 0x3f; - frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4; - this->frame_buffer[3] = frame_size; - - /* ac3 seems to be swabbed data */ - swab(buf->mem,this->frame_buffer+4, buf->num_frames ); - this->driver->write(this->driver, this->frame_buffer, 1536); - - break; case AO_CAP_MODE_AC5: - memset(this->frame_buffer,0x00,6144); - this->frame_buffer[0] = 0xf872; /* spdif syncword */ - this->frame_buffer[1] = 0x4e1f; /* ............. */ - data = (uint8_t *)&buf->mem[0]; - - if ((data[0] != 0x7f) || - (data[1] != 0xfe) || - (data[2] != 0x80) || - (data[3] != 0x01)) { - continue; - } - ac5_type=((data[4] & 0x01) << 6) | ((data[5] >>2) & 0x3f); - /* printf("AC5 type=%d\n",ac5_type); */ - switch(ac5_type) { - case 0x0f: - this->frame_buffer[2] = 0x000b; /* DTS */ - break; - case 0x1f: - this->frame_buffer[2] = 0x000c; /* DTS */ - break; - case 0x3f: - this->frame_buffer[2] = 0x000d; /* DTS */ - break; - default: - this->frame_buffer[2] = 0x0000; /* DTS */ - break; - } - - ac5_length=((data[5] & 0x03) << 12) | - ((data[6] & 0xff) << 4) | - ((data[7] & 0xf0) >> 4); - ac5_length++; - ac5_length=ac5_length * buf->frame_header_count ; - - if (ac5_length > 4088) { - /* Biggest PCM length from AC5 is 4096 */ - break; - } - this->frame_buffer[3] = ac5_length << 3; /* Convert bytes to bits */ - - /* ac3 seems to be swabbed data */ - swab(buf->mem,this->frame_buffer+4, ac5_length ); - - if (ac5_length <= 248) { - ac5_pcm_length = 64; - } else if (ac5_length <= 504) { - ac5_pcm_length = 128; - } else if (ac5_length <= 1016) { - ac5_pcm_length = 256; - } else if (ac5_length <= 2040) { - ac5_pcm_length = 512; - } else if (ac5_length <= 4088) { - ac5_pcm_length = 1024; - } else { - printf("BAD AC5 length\n"); - break; - } - if (ac5_pcm_length < (512 * buf->frame_header_count)) { - ac5_pcm_length = 512 * buf->frame_header_count ; - } - /* printf("DTS length=%d\n",ac5_pcm_length); */ - this->driver->write(this->driver, this->frame_buffer, ac5_pcm_length); - + this->driver->write(this->driver, buf->mem, buf->num_frames); break; } -- cgit v1.2.3