summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Courtier-Dutton <jcdutton@users.sourceforge.net>2001-08-22 10:51:05 +0000
committerJames Courtier-Dutton <jcdutton@users.sourceforge.net>2001-08-22 10:51:05 +0000
commit30aa3b0d59e128bdf0e1311abf1945cd5df4b411 (patch)
treef7ad04aa17a472c098b660c9e4690c7c1c8f5a8b
parentd023bb7e503e744c763f8b1a577b4f8b3233b999 (diff)
downloadxine-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.am3
-rw-r--r--src/audio_out/audio_alsa_out.c475
-rw-r--r--src/audio_out/audio_oss_out.c4
-rw-r--r--src/xine-engine/audio_out.c110
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 );