summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames Courtier-Dutton <jcdutton@users.sourceforge.net>2001-12-09 18:31:01 +0000
committerJames Courtier-Dutton <jcdutton@users.sourceforge.net>2001-12-09 18:31:01 +0000
commit7e0416720dbeb41dec90ccb80428e5aa560e1a65 (patch)
tree0e6c88425d3a6579a519c920c12990644e6d7c0a /src
parentd97842f5815df66d5c653c88aa98cf4b98202794 (diff)
downloadxine-lib-7e0416720dbeb41dec90ccb80428e5aa560e1a65.tar.gz
xine-lib-7e0416720dbeb41dec90ccb80428e5aa560e1a65.tar.bz2
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
Diffstat (limited to 'src')
-rw-r--r--src/liba52/xine_decoder.c82
-rw-r--r--src/libdts/xine_decoder.c100
-rw-r--r--src/xine-engine/audio_out.c137
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 <stdlib.h>
#include <unistd.h>
@@ -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 <stdlib.h>
#include <unistd.h>
@@ -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 <andy@alsaplayer.org>
@@ -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;
}