diff options
author | James Courtier-Dutton <jcdutton@users.sourceforge.net> | 2001-08-22 10:51:05 +0000 |
---|---|---|
committer | James Courtier-Dutton <jcdutton@users.sourceforge.net> | 2001-08-22 10:51:05 +0000 |
commit | 30aa3b0d59e128bdf0e1311abf1945cd5df4b411 (patch) | |
tree | f7ad04aa17a472c098b660c9e4690c7c1c8f5a8b | |
parent | d023bb7e503e744c763f8b1a577b4f8b3233b999 (diff) | |
download | xine-lib-30aa3b0d59e128bdf0e1311abf1945cd5df4b411.tar.gz xine-lib-30aa3b0d59e128bdf0e1311abf1945cd5df4b411.tar.bz2 |
Both OSS and ALSA09 are now supported by the new audio_out architecture.
Some minor cleanup.
Please see xine-lib/src/xine-engine/audio_out.c
for a list of what works and what does not.
CVS patchset: 461
CVS date: 2001/08/22 10:51:05
-rw-r--r-- | src/audio_out/Makefile.am | 3 | ||||
-rw-r--r-- | src/audio_out/audio_alsa_out.c | 475 | ||||
-rw-r--r-- | src/audio_out/audio_oss_out.c | 4 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 110 |
4 files changed, 217 insertions, 375 deletions
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am index c34fa49cd..a57a65c2f 100644 --- a/src/audio_out/Makefile.am +++ b/src/audio_out/Makefile.am @@ -3,6 +3,7 @@ CFLAGS = @GLOBAL_CFLAGS@ -DXINE_COMPILE $(ALSA_CFLAGS) $(ESD_CFLAGS) $(IRIXAL_CF #EXTRA_DIST = audio_alsa_out.c audio_alsa05_out.c audio_esd_out.c \ # audio_sun_out.c audio_arts_out.c ## audio_irixal_out.c +EXTRA_DIST = audio_alsa_out.c LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic @@ -21,7 +22,7 @@ if HAVE_ALSA05 #alsa05_module = xineplug_ao_out_alsa05.la endif if HAVE_ALSA09 -#alsa_module = xineplug_ao_out_alsa.la +alsa_module = xineplug_ao_out_alsa.la endif endif diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c index 6512a711c..3e454f9b6 100644 --- a/src/audio_out/audio_alsa_out.c +++ b/src/audio_out/audio_alsa_out.c @@ -25,7 +25,7 @@ * (c) 2001 James Courtier-Dutton <James@superbug.demon.co.uk> * * - * $Id: audio_alsa_out.c,v 1.15 2001/08/20 11:15:57 joachim_koenig Exp $ + * $Id: audio_alsa_out.c,v 1.16 2001/08/22 10:51:05 jcdutton Exp $ */ #ifdef HAVE_CONFIG_H @@ -61,7 +61,6 @@ #include "xine_internal.h" #include "monitor.h" #include "audio_out.h" -#include "resample.h" #include "metronom.h" #include "utils.h" @@ -74,111 +73,40 @@ # endif #endif -#define AO_OUT_ALSA_IFACE_VERSION 1 +#define AO_OUT_ALSA_IFACE_VERSION 2 #define GAP_TOLERANCE 15000 #define MAX_MASTER_CLOCK_DIV 5000 #define MAX_GAP 90000 -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 } } -}; - - -typedef struct alsa_functions_s { - - ao_functions_t ao_functions; - - metronom_t *metronom; +typedef struct alsa_driver_s { + ao_driver_t ao_driver; char audio_dev[20]; snd_pcm_t * audio_fd; + int capabilities; int open_mode; int32_t output_sample_rate, input_sample_rate; int32_t output_rate_correction; double sample_rate_factor; uint32_t num_channels; -/* The ALSA drivers handle "frames" instead of bytes. - * So for a Stereo 16 Bit Sample, each frame would equil 4 bytes. - * For this plugin, we will use frames instead of bytes for everything. - * The term sample is also equil to frames - */ + uint32_t bits_per_sample; + uint32_t bytes_per_frame; uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ - int audio_step; /* pts per 32 768 frames (frame = #bytes/2(16 bits)/channels) */ -/* frames = pts * rate / pts_per_second */ -/* pts = frame * pts_per_second / rate */ - int32_t bytes_per_kpts; /* bytes per 1024/90000 sec */ - - - snd_pcm_sframes_t pts_per_second; /* pts per second */ - - int16_t *zero_space; - int audio_started; - int capabilities; - - uint32_t last_audio_vpts; -} alsa_functions_t; - -void write_pause_burst(alsa_functions_t *,int ); -void write_burst(alsa_functions_t *,u_char *, size_t ); +} alsa_driver_t; static snd_output_t *jcd_out; /* * open the audio device for writing to */ -static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int mode) +static int ao_alsa_open(ao_driver_t *self_gen, uint32_t bits, uint32_t rate, int mode) { - alsa_functions_t *this = (alsa_functions_t *) this_gen; + alsa_driver_t *self = (alsa_driver_t *) self_gen; snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK; snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; @@ -204,23 +132,26 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m error ("ALSA Driver only supports AC3/stereo output modes at the moment"); return -1; } else { - this->num_channels = 2; + self->num_channels = 2; } - if (this->audio_fd != NULL) { + if (self->audio_fd != NULL) { error ("Already open...WHY!"); - snd_pcm_close (this->audio_fd); + snd_pcm_close (self->audio_fd); } - this->input_sample_rate = rate; - this->bytes_in_buffer = 0; - this->output_rate_correction = 0; - this->audio_started = 0; - this->open_mode = mode; - this->last_audio_vpts = 0; + + self->open_mode = mode; + self->input_sample_rate = rate; + self->bits_per_sample = bits; + self->bytes_in_buffer = 0; + self->output_rate_correction = 0; + self->audio_started = 0; + /* FIXME: Can use an ALSA function here */ + self->bytes_per_frame=(self->bits_per_sample*self->num_channels)/8; /* * open audio device */ - err=snd_pcm_open(&this->audio_fd, this->audio_dev, direction, open_mode); + err=snd_pcm_open(&self->audio_fd, self->audio_dev, direction, open_mode); if(err <0 ) { error("snd_pcm_open() failed: %s", snd_strerror(err)); error(">>> Check if another program don't already use PCM <<<"); @@ -231,7 +162,7 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m snd_pcm_info_alloca(&info); - if ((err = snd_pcm_info(this->audio_fd, info)) < 0) { + if ((err = snd_pcm_info(self->audio_fd, info)) < 0) { fprintf(stderr, "info: %s\n", snd_strerror(err)); goto __close; } @@ -276,38 +207,38 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m /* We wanted non blocking open but now put it back to normal */ - snd_pcm_nonblock(this->audio_fd, 0); + snd_pcm_nonblock(self->audio_fd, 0); /* * configure audio device */ - err = snd_pcm_hw_params_any(this->audio_fd, params); + err = snd_pcm_hw_params_any(self->audio_fd, params); if (err < 0) { error("Broken configuration for this PCM: no configurations available"); goto __close; } /* set interleaved access */ - err = snd_pcm_hw_params_set_access(this->audio_fd, params, + err = snd_pcm_hw_params_set_access(self->audio_fd, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { error("Access type not available"); goto __close; } - err = snd_pcm_hw_params_set_format(this->audio_fd, params, bits == 16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8); + err = snd_pcm_hw_params_set_format(self->audio_fd, params, bits == 16 ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8); if (err < 0) { error("Sample format non available"); goto __close; } - err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels); + err = snd_pcm_hw_params_set_channels(self->audio_fd, params, self->num_channels); if (err < 0) { error("Channels count non available"); goto __close; } - err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, rate, 0); + err = snd_pcm_hw_params_set_rate_near(self->audio_fd, params, rate, 0); if (err < 0) { error("Rate not available"); goto __close; } - buffer_time = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, + buffer_time = snd_pcm_hw_params_set_buffer_time_near(self->audio_fd, params, 500000, 0); if (buffer_time < 0) { error("Buffer time not available"); @@ -317,11 +248,11 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m period_time = 10000 * 2; do { period_time /= 2; - tmp = snd_pcm_hw_params_set_period_time_near(this->audio_fd, params, + tmp = snd_pcm_hw_params_set_period_time_near(self->audio_fd, params, period_time, 0); if (tmp == period_time) { period_time /= 3; - tmp = snd_pcm_hw_params_set_period_time_near(this->audio_fd, params, + tmp = snd_pcm_hw_params_set_period_time_near(self->audio_fd, params, period_time, 0); if (tmp == period_time) period_time = 10000 * 2; @@ -335,7 +266,7 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m error("Buffer time and period time match, could not use"); goto __close; } - if ((err = snd_pcm_hw_params(this->audio_fd, params)) < 0) { + if ((err = snd_pcm_hw_params(self->audio_fd, params)) < 0) { error("PCM hw_params failed: %s", snd_strerror(err)); goto __close; } @@ -343,103 +274,77 @@ static int ao_open(ao_functions_t *this_gen, uint32_t bits, uint32_t rate, int m - this->output_sample_rate = this->input_sample_rate; - this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate; - this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 - / this->input_sample_rate; - this->bytes_per_kpts = this->output_sample_rate * this->num_channels * 2 * 1024 / 90000; - - this->metronom->set_audio_rate(this->metronom, this->audio_step); + self->output_sample_rate = self->input_sample_rate; + self->sample_rate_factor = (double) self->output_sample_rate / (double) self->input_sample_rate; /* * audio buffer size handling */ /* Copy current parameters into swparams */ - snd_pcm_sw_params_current(this->audio_fd, swparams); - tmp=snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 4); - tmp=snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, 1); - tmp=snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, 1); + snd_pcm_sw_params_current(self->audio_fd, swparams); + tmp=snd_pcm_sw_params_set_xfer_align(self->audio_fd, swparams, 4); + tmp=snd_pcm_sw_params_set_avail_min(self->audio_fd, swparams, 1); + tmp=snd_pcm_sw_params_set_start_threshold(self->audio_fd, swparams, 1); /* Install swparams into current parameters */ - snd_pcm_sw_params(this->audio_fd, swparams); + snd_pcm_sw_params(self->audio_fd, swparams); - snd_pcm_dump_setup(this->audio_fd, jcd_out); + snd_pcm_dump_setup(self->audio_fd, jcd_out); snd_pcm_sw_params_dump(swparams, jcd_out); - // write_pause_burst(this,0); + // write_pause_burst(self,0); return 1; __close: - snd_pcm_close (this->audio_fd); - this->audio_fd=NULL; + snd_pcm_close (self->audio_fd); + self->audio_fd=NULL; return -1; } -static uint32_t ao_get_current_pos (alsa_functions_t *this) +static int ao_alsa_num_channels(ao_driver_t *self_gen) +{ + alsa_driver_t *self = (alsa_driver_t *) self_gen; + return self->num_channels; +} + +static int ao_alsa_bytes_per_frame(ao_driver_t *self_gen) +{ + alsa_driver_t *self = (alsa_driver_t *) self_gen; + return self->bytes_per_frame; +} + + + +static int ao_alsa_delay (ao_driver_t *self_gen) { snd_pcm_sframes_t pos ; snd_pcm_status_t *pcm_stat; snd_pcm_sframes_t delay; int err; - + alsa_driver_t *self = (alsa_driver_t *) self_gen; snd_pcm_status_alloca(&pcm_stat); - snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status(self->audio_fd, pcm_stat); /* Dump ALSA info to stderr */ /* snd_pcm_status_dump(pcm_stat, jcd_out); */ - if (this->audio_started) { - err=snd_pcm_delay( this->audio_fd, &delay); + if (self->audio_started) { + err=snd_pcm_delay( self->audio_fd, &delay); if(err < 0) { //Hide error report error("snd_pcm_delay() failed"); - return this->bytes_in_buffer; - } - pos = delay * 2 * this->num_channels; - } else { - pos=this->bytes_in_buffer; - } - return pos; -} - -static void ao_fill_gap (alsa_functions_t *this, uint32_t pts_len) { - - int num_bytes ; - - if (pts_len > MAX_GAP) - pts_len = MAX_GAP; - num_bytes = pts_len * this->bytes_per_kpts / 1024; - num_bytes = (num_bytes / (2*this->num_channels)) * (2*this->num_channels); - - if(this->open_mode == AO_CAP_MODE_AC3) { - //write_pause_burst(this,0); - //printf("audio_alsa_out: SPDIF write pause\n"); - return; - } - - printf ("audio_alsa_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len); - - this->bytes_in_buffer += num_bytes; - - while (num_bytes>0) { - if (num_bytes>8192) { - write_burst(this, (unsigned char *)this->zero_space, 8192 / (2 * this->num_channels)); - num_bytes -= 8192; - } else { - write_burst(this, (unsigned char *)this->zero_space, num_bytes / (2 * this->num_channels)); - num_bytes = 0; + return 0; } } + return delay; } - - -void xrun(alsa_functions_t *this) +void xrun(alsa_driver_t *self) { snd_pcm_status_t *status; int res; snd_pcm_status_alloca(&status); - if ((res = snd_pcm_status(this->audio_fd, status))<0) { + if ((res = snd_pcm_status(self->audio_fd, status))<0) { printf("status error: %s", snd_strerror(res)); return; } @@ -450,7 +355,7 @@ void xrun(alsa_functions_t *this) timersub(&now, &tstamp, &diff); fprintf(stderr, "xrun!!! (at least %.3f ms long)\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0); - if ((res = snd_pcm_prepare(this->audio_fd))<0) { + if ((res = snd_pcm_prepare(self->audio_fd))<0) { printf("xrun: prepare error: %s", snd_strerror(res)); return; } @@ -458,201 +363,51 @@ void xrun(alsa_functions_t *this) } } -void write_burst(alsa_functions_t *this,u_char *data, size_t count) +static int ao_alsa_write(ao_driver_t *self_gen,int16_t *data, uint32_t count) { ssize_t r; + alsa_driver_t *self = (alsa_driver_t *) self_gen; while( count > 0) { - r = snd_pcm_writei(this->audio_fd, data, count); + r = snd_pcm_writei(self->audio_fd, data, count); if (r == -EAGAIN || (r >=0 && r < count)) { - snd_pcm_wait(this->audio_fd, 1000); + snd_pcm_wait(self->audio_fd, 1000); } else if (r == -EPIPE) { - xrun(this); + xrun(self); } if (r > 0) { count -= r; - data += r * 2 * this->num_channels; + /* FIXME: maybe not *2 as int16 */ + data += r * 2 * self->num_channels; } } - + /* FIXME: What should this really be? */ +return 1; } -void write_pause_burst(alsa_functions_t *this,int error) +static void ao_alsa_close(ao_driver_t *self_gen) { -#define BURST_SIZE 6144 - - unsigned char buf[8192]; - unsigned short *sbuf = (unsigned short *)&buf[0]; - - sbuf[0] = 0xf872; - sbuf[1] = 0x4e1f; - - if (error == 0) - // Audio ES Channel empty, wait for DD Decoder or pause - sbuf[2] = 0x0003; - else - // user stop, skip or error - sbuf[2] = 0x0103; - - sbuf[3] = 0x0020; - sbuf[4] = 0x0000; - sbuf[5] = 0x0000; - - memset(&sbuf[6], 0, BURST_SIZE - 96); - - write_burst(this,(u_char *)sbuf, BURST_SIZE / 4); + alsa_driver_t *self = (alsa_driver_t *) self_gen; + if(self->audio_fd) snd_pcm_close(self->audio_fd); + self->audio_fd = NULL; } - - -static int ao_write_audio_data(ao_functions_t *this_gen, - int16_t* output_samples, uint32_t num_samples, - uint32_t pts_) -{ - - alsa_functions_t *this = (alsa_functions_t *) this_gen; - uint32_t vpts, - pos, - buffer_vpts; - int32_t gap; - int bDropPackage; - uint16_t sample_buffer[8192]; - int num_output_samples; - int frame_size; - int fscod; - int frmsizecod; - uint8_t *data; - snd_pcm_sframes_t res = 0; - - if (this->audio_fd == NULL) { - error("Nothing open"); - return 1; - } - - if(this->open_mode == AO_CAP_MODE_AC3) - num_samples = 1536; /* FIXME */ - - vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples); - - - - if (vpts<this->last_audio_vpts) { - /* reject this */ - - return 1; - } - this->last_audio_vpts = vpts; - bDropPackage = 0; - - pos = ao_get_current_pos (this) ; - -// if (pos>this->bytes_in_buffer) /* buffer ran dry */ -// this->bytes_in_buffer = pos; - -//printf("samples %d pos %d bytes_in_buffer %d ",num_samples,pos,this->bytes_in_buffer); - buffer_vpts = this->metronom->get_current_time (this->metronom); -//printf("buffer_vpts %d vpts %d ",buffer_vpts,vpts); - buffer_vpts += (this->bytes_in_buffer - pos) * 1024 / this->bytes_per_kpts; - this->bytes_in_buffer -= (this->bytes_in_buffer - pos); - - gap = vpts - buffer_vpts; - -//printf("gap %d \n",gap); - - - if (gap>GAP_TOLERANCE) { - ao_fill_gap (this, gap); - - /* keep xine responsive */ - - if (gap>MAX_GAP) - return 0; - - } else if (gap<-GAP_TOLERANCE) { - bDropPackage = 1; -//printf("audio_alsa_out: drop package\n"); - } - - - - /* - * resample and output samples - */ - - if(this->open_mode == AO_CAP_MODE_AC3) bDropPackage=0; - - - if (!bDropPackage) { - if ((this->open_mode & AO_CAP_MODE_AC3) == 0) { - num_output_samples = num_samples * (this->output_sample_rate) / this->input_sample_rate; - audio_out_resample_stereo (output_samples, num_samples, - sample_buffer, num_output_samples); - do { - res=snd_pcm_avail_update(this->audio_fd); - usleep(3200); - } while (res<num_output_samples+512); - } else { - num_output_samples = num_samples; - sample_buffer[0] = 0xf872; //spdif syncword - sample_buffer[1] = 0x4e1f; // ............. - sample_buffer[2] = 0x0001; // AC3 data - - data = (uint8_t *)&output_samples[1]; // skip AC3 sync - fscod = (data[2] >> 6) & 0x3; - frmsizecod = data[2] & 0x3f; - frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4; - sample_buffer[3] = frame_size; - - // ac3 seems to be swabbed data - swab(&output_samples[0],&sample_buffer[4], num_samples * 2 ); - } - - - - /* Special note, the new ALSA outputs in counts of frames. - * A Frame is one sample for all channels, so here a Stereo 16 bits frame is 4 bytes. - */ - write_burst(this, (unsigned char *)sample_buffer, num_output_samples); - /* - * step values - */ - this->bytes_in_buffer += num_samples * 2 * this->num_channels ; - this->audio_started = 1; - } - - return 1; -} - - -static void ao_close(ao_functions_t *this_gen) -{ - alsa_functions_t *this = (alsa_functions_t *) this_gen; - if(this->audio_fd) snd_pcm_close(this->audio_fd); - this->audio_fd = NULL; -} - -static uint32_t ao_get_capabilities (ao_functions_t *this_gen) { - alsa_functions_t *this = (alsa_functions_t *) this_gen; - return this->capabilities; -} - -static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) { - alsa_functions_t *this = (alsa_functions_t *) this_gen; - this->metronom = metronom; +static uint32_t ao_alsa_get_capabilities (ao_driver_t *self_gen) { + alsa_driver_t *self = (alsa_driver_t *) self_gen; + return self->capabilities; } -static void ao_exit(ao_functions_t *this_gen) +static void ao_alsa_exit(ao_driver_t *self_gen) { - alsa_functions_t *this = (alsa_functions_t *) this_gen; - if (this->audio_fd) snd_pcm_close(this->audio_fd); - free (this->zero_space); - free (this); + alsa_driver_t *self = (alsa_driver_t *) self_gen; + if (self->audio_fd) snd_pcm_close(self->audio_fd); + free (self); } /* * */ -static int ao_get_property (ao_functions_t *this, int property) { +static int ao_alsa_get_property (ao_driver_t *self, int property) { /* FIXME: implement some properties switch(property) { @@ -670,7 +425,7 @@ static int ao_get_property (ao_functions_t *this, int property) { /* * */ -static int ao_set_property (ao_functions_t *this, int property, int value) { +static int ao_alsa_set_property (ao_driver_t *self, int property, int value) { /* FIXME: Implement property support. switch(property) { @@ -686,22 +441,22 @@ static int ao_set_property (ao_functions_t *this, int property, int value) { return ~value; } -ao_functions_t *init_audio_out_plugin (config_values_t *config) { +ao_driver_t *init_audio_out_plugin (config_values_t *config) { - alsa_functions_t *this; + alsa_driver_t *self; int card; int dev; int err; char *pcm_device; char *ac3_device; - this = (alsa_functions_t *) malloc (sizeof (alsa_functions_t)); + self = (alsa_driver_t *) malloc (sizeof (alsa_driver_t)); pcm_device = config->lookup_str(config,"alsa_pcm_device", "hw:0,0"); ac3_device = config->lookup_str(config,"alsa_ac3_device", "hw:0,2"); - strcpy(this->audio_dev,pcm_device); + strcpy(self->audio_dev,pcm_device); /* * find best device driver/channel @@ -710,36 +465,34 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) { * open that device */ - err=snd_pcm_open(&this->audio_fd, this->audio_dev, SND_PCM_STREAM_PLAYBACK, 0); + err=snd_pcm_open(&self->audio_fd, self->audio_dev, SND_PCM_STREAM_PLAYBACK, 0); if(err <0 ) { error("snd_pcm_open() failed: %d", err); error(">>> Check if another program don't already use PCM <<<"); return NULL; } - snd_pcm_close (this->audio_fd); - this->audio_fd=NULL; - this->output_sample_rate = 0; - this->capabilities = AO_CAP_MODE_STEREO; + snd_pcm_close (self->audio_fd); + self->audio_fd=NULL; + self->output_sample_rate = 0; + self->capabilities = AO_CAP_MODE_STEREO; if (config->lookup_int (config, "ac3_pass_through", 0)) { - this->capabilities |= AO_CAP_MODE_AC3; - strcpy(this->audio_dev,ac3_device); + self->capabilities |= AO_CAP_MODE_AC3; + strcpy(self->audio_dev,ac3_device); printf("AC3 pass through activated\n"); } - - this->zero_space = malloc (8192); - memset (this->zero_space, 0, 8192); - - this->ao_functions.get_capabilities = ao_get_capabilities; - this->ao_functions.get_property = ao_get_property; - this->ao_functions.set_property = ao_set_property; - this->ao_functions.connect = ao_connect; - this->ao_functions.open = ao_open; - this->ao_functions.write_audio_data = ao_write_audio_data; - this->ao_functions.close = ao_close; - this->ao_functions.exit = ao_exit; - - return &this->ao_functions; + self->ao_driver.get_capabilities = ao_alsa_get_capabilities; + self->ao_driver.get_property = ao_alsa_get_property; + self->ao_driver.set_property = ao_alsa_set_property; + self->ao_driver.open = ao_alsa_open; + self->ao_driver.num_channels = ao_alsa_num_channels; + self->ao_driver.bytes_per_frame = ao_alsa_bytes_per_frame; + self->ao_driver.delay = ao_alsa_delay; + self->ao_driver.write = ao_alsa_write; + self->ao_driver.close = ao_alsa_close; + self->ao_driver.exit = ao_alsa_exit; + + return &self->ao_driver; } static ao_info_t ao_info_alsa9 = { diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c index 0d13bef40..82227e5b2 100644 --- a/src/audio_out/audio_oss_out.c +++ b/src/audio_out/audio_oss_out.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: audio_oss_out.c,v 1.30 2001/08/21 19:39:50 jcdutton Exp $ + * $Id: audio_oss_out.c,v 1.31 2001/08/22 10:51:05 jcdutton Exp $ * * 20-8-2001 First implementation of Audio sync and Audio driver separation. * Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk @@ -67,8 +67,6 @@ #include "xine_internal.h" #include "monitor.h" #include "audio_out.h" -#include "resample.h" -#include "metronom.h" #include "utils.h" #ifndef AFMT_S16_NE diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 19273fdfd..24fff6929 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -17,10 +17,12 @@ * 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.3 2001/08/21 19:39:50 jcdutton Exp $ + * $Id: audio_out.c,v 1.4 2001/08/22 10:51:05 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> * 20-8-2001 First implementation of Audio sync and Audio driver separation. - * Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk + * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk * * General Programming Guidelines: - * New concept of an "audio_frame". @@ -32,6 +34,11 @@ * when dealing with audio_bytes instead of audio_frames. * * The number of samples passed to/from the audio driver is also sent in units of audio_frames. + * + * Currently, James has tested with OSS: Standard stereo out, SPDIF PCM, SPDIF AC3 + * ALSA: Standard stereo out + * No testing has been done of ALSA SPDIF AC3 or any 4,5,5.1 channel output. + * Currently, I don't think resampling functions, as I cannot test it. */ /* required for swab() */ @@ -100,6 +107,55 @@ #define DSP_TEMPLATE "/dev/dsp%d" #endif +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 } } +}; + /* * open the audio device for writing to */ @@ -111,17 +167,17 @@ static int ao_open(ao_instance_t *self, printf("open failed!\n"); return -1; }; -// self->frame_rate_factor = (double) self->output_frame_rate / (double) self->input_frame_rate; - self->mode = mode; + self->mode = mode; self->input_frame_rate = rate; - self->frames_in_buffer = 0; - self->audio_started = 0; - self->last_audio_vpts = 0; + self->frames_in_buffer = 0; + self->audio_started = 0; + self->last_audio_vpts = 0; + self->do_resample = 0; /* Resampling currently not working. */ self->output_frame_rate=rate; self->num_channels = self->driver->num_channels(self->driver); - self->frame_rate_factor = (double) 1 / (double) 1; + self->frame_rate_factor = (double) self->output_frame_rate / (double) self->input_frame_rate; /* Alway produces 1 at the moment */ self->audio_step = (uint32_t) 90000 * (uint32_t) 32768 / self->input_frame_rate; self->frames_per_kpts = self->output_frame_rate * self->num_channels * 2 * 1024 / 90000; @@ -160,7 +216,37 @@ static void ao_fill_gap (ao_instance_t *self, uint32_t pts_len) { } } +/* + * This routine is currently not used, but I do not want to loose it. + * I think "(c) 2001 Andy Lo A Foe <andy@alsaplayer.org>" originally added it + * to ./xine-lib/src/audio_out/audio_alsa_out.c before the architecture changes + * So it has moved to here. + */ + +void write_pause_burst(alsa_instance_t *this,int error) +{ +#define BURST_SIZE 6144 + + unsigned char buf[8192]; + unsigned short *sbuf = (unsigned short *)&buf[0]; + + sbuf[0] = 0xf872; + sbuf[1] = 0x4e1f; + if (error == 0) + // Audio ES Channel empty, wait for DD Decoder or pause + sbuf[2] = 0x0003; + else + // user stop, skip or error + sbuf[2] = 0x0103; + + sbuf[3] = 0x0020; + sbuf[4] = 0x0000; + sbuf[5] = 0x0000; + + memset(&sbuf[6], 0, BURST_SIZE - 96); + self->driver->write(self->driver, u_char * sbuf, BURST_SIZE / 4); +} static int ao_write(ao_instance_t *self, int16_t* output_frames, uint32_t num_frames, @@ -276,8 +362,12 @@ static int ao_write(ao_instance_t *self, self->frame_buffer[0] = 0xf872; //spdif syncword self->frame_buffer[1] = 0x4e1f; // ............. self->frame_buffer[2] = 0x0001; // AC3 data - self->frame_buffer[3] = num_frames * 8; - self->frame_buffer[4] = 0x0b77; // AC3 syncwork already in output_frames + + data = (uint8_t *)&output_samples[1]; // skip AC3 sync + fscod = (data[2] >> 6) & 0x3; + frmsizecod = data[2] & 0x3f; + frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4; + sample_buffer[3] = frame_size; // ac3 seems to be swabbed data swab(output_frames,self->frame_buffer+4, num_frames ); |