summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine.h.tmpl.in18
-rw-r--r--src/audio_out/Makefile.am14
-rw-r--r--src/audio_out/audio_oss_out.c472
-rw-r--r--src/libac3/xine_decoder.c10
-rw-r--r--src/liblpcm/xine_decoder.c8
-rw-r--r--src/libmad/xine_decoder.c8
-rw-r--r--src/libmpg123/interface.c4
-rw-r--r--src/libmpg123/layer1.c2
-rw-r--r--src/libmpg123/layer2.c2
-rw-r--r--src/libmpg123/layer3.c2
-rw-r--r--src/libmpg123/mpglib.h6
-rw-r--r--src/libmpg123/xine_decoder.c6
-rw-r--r--src/libw32dll/w32codec.c8
-rw-r--r--src/xine-engine/Makefile.am4
-rw-r--r--src/xine-engine/audio_out.c336
-rw-r--r--src/xine-engine/audio_out.h113
-rw-r--r--src/xine-engine/load_plugins.c8
-rw-r--r--src/xine-engine/xine.c9
-rw-r--r--src/xine-engine/xine_internal.h10
19 files changed, 641 insertions, 399 deletions
diff --git a/include/xine.h.tmpl.in b/include/xine.h.tmpl.in
index b91de236b..f6adb91b5 100644
--- a/include/xine.h.tmpl.in
+++ b/include/xine.h.tmpl.in
@@ -28,7 +28,7 @@
\endverbatim
*/
/*
- * $Id: xine.h.tmpl.in,v 1.36 2001/08/17 16:15:36 f1rmb Exp $
+ * $Id: xine.h.tmpl.in,v 1.37 2001/08/21 19:39:50 jcdutton Exp $
*
*/
@@ -431,10 +431,10 @@ struct vo_driver_s {
*/
typedef void xine_t;
/**
- * \struct ao_functions_t
+ * \struct ao_driver_t
* Opaque data type.
*/
-typedef void ao_functions_t;
+typedef void ao_driver_t;
/**
* \struct cfg_data_t
* Opaque data type.
@@ -564,7 +564,7 @@ typedef void (*gui_branched_cb_t) (void);
/** @} end of demux_strategy */
/**
- * \fn xine_t *xine_init (vo_driver_t *vo, ao_functions_t *ao, config_values_t *config, gui_stream_end_cb_t stream_end_cb, gui_get_next_mrl_cb_t get_next_mrl_cb, gui_branched_cb_t branched_cb);
+ * \fn xine_t *xine_init (vo_driver_t *vo, ao_driver_t *ao, config_values_t *config, gui_stream_end_cb_t stream_end_cb, gui_get_next_mrl_cb_t get_next_mrl_cb, gui_branched_cb_t branched_cb);
* \brief Initialisation of xine.
* \param vo video driver ( #see @ref xine_load_video_output_plugin() )
* \param ao audio driver ( #see @ref xine_load_audio_output_plugin() )
@@ -573,7 +573,7 @@ typedef void (*gui_branched_cb_t) (void);
* \param get_next_mrl_cb called to find out next mrl for seamless branching
* \param branched_cb called if seamless branch was taken
* \return Current xine engine configuration
- * \sa vo_driver_t, ao_functions_t, config_values_t, gui_stream_end_cb_t, gui_get_next_mrl_cb_t, gui_branched_cb_t
+ * \sa vo_driver_t, ao_driver_t, config_values_t, gui_stream_end_cb_t, gui_get_next_mrl_cb_t, gui_branched_cb_t
* \warning This function should be called before any other xine_*() function.
*
* Init of xine. It should called once at startup.
@@ -582,7 +582,7 @@ typedef void (*gui_branched_cb_t) (void);
*
*/
xine_t *xine_init (vo_driver_t *vo,
- ao_functions_t *ao,
+ ao_driver_t *ao,
config_values_t *config,
gui_stream_end_cb_t stream_end_cb,
gui_get_next_mrl_cb_t get_next_mrl_cb,
@@ -1078,13 +1078,13 @@ vo_driver_t *xine_load_video_output_plugin(config_values_t *config,
char **xine_list_audio_output_plugins (void);
/**
- * \fn ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, char *id)
+ * \fn ao_driver_t *xine_load_audio_output_plugin(config_values_t *config, char *id)
* \param config current configuration ( #see config_file_init() )
* \param id driver name.
* \brief load a specific audio output plugin.
- * \sa ao_functions_t
+ * \sa ao_driver_t
*/
-ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, char *id);
+ao_driver_t *xine_load_audio_output_plugin(config_values_t *config, char *id);
/** @} end of loadplugins_group */
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am
index 00368063d..c34fa49cd 100644
--- a/src/audio_out/Makefile.am
+++ b/src/audio_out/Makefile.am
@@ -1,7 +1,7 @@
CFLAGS = @GLOBAL_CFLAGS@ -DXINE_COMPILE $(ALSA_CFLAGS) $(ESD_CFLAGS) $(IRIXAL_CFLAGS) $(ARTS_CFLAGS)
-EXTRA_DIST = audio_alsa_out.c audio_alsa05_out.c audio_esd_out.c \
- audio_sun_out.c audio_arts_out.c
+#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
LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
@@ -18,19 +18,19 @@ endif
#
if HAVE_ALSA
if HAVE_ALSA05
-alsa05_module = xineplug_ao_out_alsa05.la
+#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
if HAVE_ESD
-esd_module = xineplug_ao_out_esd.la
+#esd_module = xineplug_ao_out_esd.la
endif
if HAVE_SUNAUDIO
-sun_module = xineplug_ao_out_sun.la
+#sun_module = xineplug_ao_out_sun.la
endif
## if HAVE_IRIXAL
@@ -38,7 +38,7 @@ endif
## endif
if HAVE_ARTS
-arts_module = xineplug_ao_out_arts.la
+#arts_module = xineplug_ao_out_arts.la
endif
##
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index 575ddf448..0d13bef40 100644
--- a/src/audio_out/audio_oss_out.c
+++ b/src/audio_out/audio_oss_out.c
@@ -17,7 +17,22 @@
* 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.29 2001/08/18 23:28:26 guenter Exp $
+ * $Id: audio_oss_out.c,v 1.30 2001/08/21 19:39:50 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
+ *
+ * General Programming Guidelines: -
+ * New concept of an "audio_frame".
+ * An audio_frame consists of all the samples required to fill every audio channel to a full amount of bits.
+ * So, it does not mater how many bits per sample, or how many audio channels are being used, the number of audio_frames is the same.
+ * E.g. 16 bit stereo is 4 bytes, but one frame.
+ * 16 bit 5.1 surround is 12 bytes, but one frame.
+ * The purpose of this is to make the audio_sync code a lot more readable, rather than having to multiply by the amount of channels all the time
+ * 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.
+ * `
*/
/* required for swab() */
@@ -69,7 +84,7 @@
# define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */
#endif
-#define AO_OUT_OSS_IFACE_VERSION 1
+#define AO_OUT_OSS_IFACE_VERSION 2
#define AUDIO_NUM_FRAGMENTS 15
#define AUDIO_FRAGMENT_SIZE 8192
@@ -88,12 +103,9 @@
static int checked_getoptr = 0;
-typedef struct oss_functions_s {
-
- ao_functions_t ao_functions;
-
- metronom_t *metronom;
+typedef struct oss_driver_s {
+ ao_driver_t ao_driver;
char audio_dev[20];
int audio_fd;
int capabilities;
@@ -102,98 +114,89 @@ typedef struct oss_functions_s {
int32_t output_sample_rate, input_sample_rate;
double sample_rate_factor;
uint32_t num_channels;
-
+ 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 samples (sample = #bytes/2) */
- int32_t bytes_per_kpts; /* bytes per 1024/90000 sec */
-
- uint16_t *sample_buffer;
- int16_t *zero_space;
int audio_started;
int audio_has_realtime; /* OSS driver supports real-time */
- uint32_t last_audio_vpts;
- int resample_conf;
- int do_resample;
-} oss_functions_t;
+} oss_driver_t;
/*
* open the audio device for writing to
*/
-static int ao_open(ao_functions_t *this_gen,
+static int ao_oss_open(ao_driver_t *self_gen,
uint32_t bits, uint32_t rate, int mode)
{
- oss_functions_t *this = (oss_functions_t *) this_gen;
+ oss_driver_t *self = (oss_driver_t *) self_gen;
int tmp;
printf ("audio_oss_out: ao_open rate=%d, mode=%d\n", rate, mode);
- if ( (mode & this->capabilities) == 0 ) {
+ if ( (mode & self->capabilities) == 0 ) {
printf ("audio_oss_out: unsupported mode %08x\n", mode);
return -1;
}
- if (this->audio_fd > -1) {
+ if (self->audio_fd > -1) {
- if ( (mode == this->mode) && (rate == this->input_sample_rate) ) {
+ if ( (mode == self->mode) && (rate == self->input_sample_rate) ) {
return 1;
}
- close (this->audio_fd);
+ close (self->audio_fd);
}
- this->mode = mode;
- this->input_sample_rate = rate;
- this->bytes_in_buffer = 0;
- this->audio_started = 0;
- this->last_audio_vpts = 0;
+ self->mode = mode;
+ self->input_sample_rate = rate;
+ self->bits_per_sample = bits;
+ self->bytes_in_buffer = 0;
+ self->audio_started = 0;
/*
* open audio device
*/
- this->audio_fd=open(this->audio_dev,O_WRONLY|O_NDELAY);
- if(this->audio_fd < 0) {
+ self->audio_fd=open(self->audio_dev,O_WRONLY|O_NDELAY);
+ if(self->audio_fd < 0) {
printf("audio_oss_out: Opening audio device %s: %s\n",
- this->audio_dev, strerror(errno));
+ self->audio_dev, strerror(errno));
return -1;
}
/* We wanted non blocking open but now put it back to normal */
- fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL)&~FNDELAY);
+ fcntl(self->audio_fd, F_SETFL, fcntl(self->audio_fd, F_GETFL)&~FNDELAY);
/*
* configure audio device
+ * In AC3 mode, skip all other SNDCTL commands
*/
+ if(!(mode & AO_CAP_MODE_AC3)) {
+ tmp = (mode & AO_CAP_MODE_STEREO) ? 1 : 0;
+ ioctl(self->audio_fd,SNDCTL_DSP_STEREO,&tmp);
- tmp = (mode & AO_CAP_MODE_STEREO) ? 1 : 0;
- ioctl(this->audio_fd,SNDCTL_DSP_STEREO,&tmp);
-
+ tmp = bits;
+ ioctl(self->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp);
- tmp = bits;
- ioctl(this->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp);
-
- tmp = this->input_sample_rate;
+ tmp = self->input_sample_rate;
#ifdef FORCE_44K_MAX
- if(tmp > 44100)
- tmp = 44100;
+ if(tmp > 44100)
+ tmp = 44100;
#endif
- if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) {
+ if (ioctl(self->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) {
- printf ("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n", this->input_sample_rate);
+ printf ("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n", self->input_sample_rate);
- tmp = 44100;
- if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) {
- printf ("audio_oss_out: error: 44100 Hz sampling rate not supported\n");
- return -1;
+ tmp = 44100;
+ if (ioctl(self->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) {
+ printf ("audio_oss_out: error: 44100 Hz sampling rate not supported\n");
+ return -1;
+ }
}
+ self->output_sample_rate = tmp;
+ xprintf (VERBOSE|AUDIO, "audio_oss_out: audio rate : %d requested, %d provided by device/sec\n",
+ self->input_sample_rate, self->output_sample_rate);
}
- this->output_sample_rate = tmp;
-
- xprintf (VERBOSE|AUDIO, "audio_oss_out: audio rate : %d requested, %d provided by device/sec\n",
- this->input_sample_rate, this->output_sample_rate);
-
/*
* set number of channels / ac3 throughput
*/
@@ -201,48 +204,43 @@ static int ao_open(ao_functions_t *this_gen,
switch (mode) {
case AO_CAP_MODE_MONO:
tmp = 1;
- ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
- this->num_channels = tmp;
+ ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
+ self->num_channels = tmp;
break;
case AO_CAP_MODE_STEREO:
tmp = 2;
- ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
- this->num_channels = tmp;
+ ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
+ self->num_channels = tmp;
break;
case AO_CAP_MODE_4CHANNEL:
tmp = 4;
- ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
- this->num_channels = tmp;
+ ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
+ self->num_channels = tmp;
break;
case AO_CAP_MODE_5CHANNEL:
tmp = 5;
- ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
- this->num_channels = tmp;
+ ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
+ self->num_channels = tmp;
break;
case AO_CAP_MODE_5_1CHANNEL:
tmp = 6;
- ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
- this->num_channels = tmp;
+ ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
+ self->num_channels = tmp;
break;
case AO_CAP_MODE_AC3:
tmp = AFMT_AC3;
- ioctl(this->audio_fd,SNDCTL_DSP_SETFMT,&tmp);
- this->num_channels = 2; /* FIXME: is this correct ? */
+ if (ioctl(self->audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 || tmp != AFMT_AC3) {
+ printf("audio_oss_out: AC3 SNDCTL_DSP_SETFMT failed. %d\n",tmp);
+ return -1;
+ }
+ self->num_channels = 2; /* FIXME: is this correct ? */
+ self->output_sample_rate = self->input_sample_rate;
printf ("audio_oss_out : AO_CAP_MODE_AC3\n");
break;
}
- printf ("audio_oss_out : %d channels output\n",this->num_channels);
-
- 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;
-
- xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 samples\n", this->audio_step);
- printf ("audio_out : audio_step %d pts per 32768 samples\n", this->audio_step);
-
- this->metronom->set_audio_rate(this->metronom, this->audio_step);
+ printf ("audio_oss_out : %d channels output\n",self->num_channels);
+ self->bytes_per_frame=(self->bits_per_sample*self->num_channels)/8;
/*
* audio buffer size handling
@@ -261,18 +259,18 @@ static int ao_open(ao_functions_t *this_gen,
xprintf (VERBOSE|AUDIO, "Audio buffer fragment info : %x\n",tmp);
- ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
+ ioctl(self->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
*/
/*
* Final check of realtime capability, make sure GETOPTR
* doesn't return an error.
*/
- if ( this->audio_has_realtime && !checked_getoptr ) {
+ if ( self->audio_has_realtime && !checked_getoptr ) {
count_info info;
- int ret = ioctl(this->audio_fd, SNDCTL_DSP_GETOPTR, &info);
+ int ret = ioctl(self->audio_fd, SNDCTL_DSP_GETOPTR, &info);
if ( ret == -1 && errno == EINVAL ) {
- this->audio_has_realtime = 0;
+ self->audio_has_realtime = 0;
printf("audio_oss_out: Audio driver SNDCTL_DSP_GETOPTR reports %s,"
" disabling realtime sync...\n", strerror(errno) );
printf("audio_oss_out: ...Will use video master clock for soft-sync instead\n");
@@ -281,225 +279,69 @@ static int ao_open(ao_functions_t *this_gen,
checked_getoptr = 1;
}
- switch (this->resample_conf) {
- case 1: /* force off */
- this->do_resample = 0;
- break;
- case 2: /* force on */
- this->do_resample = 1;
- break;
- default: /* AUTO */
- this->do_resample = this->output_sample_rate != this->input_sample_rate;
- }
- if (this->do_resample)
- printf("audio_oss_out: will resample audio from %d to %d\n",
- this->input_sample_rate, this->output_sample_rate);
-
return 1;
}
-static void ao_fill_gap (oss_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->mode == AO_CAP_MODE_AC3) return; /* FIXME */
-
- printf ("audio_oss_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 > ZERO_BUF_SIZE) {
- write(this->audio_fd, this->zero_space, ZERO_BUF_SIZE);
- num_bytes -= ZERO_BUF_SIZE;
- } else {
- write(this->audio_fd, this->zero_space, num_bytes);
- num_bytes = 0;
- }
- }
+static int ao_oss_num_channels(ao_driver_t *self_gen)
+{
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ return self->num_channels;
}
-static int ao_write_audio_data(ao_functions_t *this_gen,
- int16_t* output_samples, uint32_t num_samples,
- uint32_t pts_)
+static int ao_oss_bytes_per_frame(ao_driver_t *self_gen)
{
-
- oss_functions_t *this = (oss_functions_t *) this_gen;
- uint32_t vpts, buffer_vpts;
- int32_t gap;
- int bDropPackage;
- count_info info;
- int pos;
-
- if (this->audio_fd<0)
- return 1;
-
- vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples);
-
- xprintf (VERBOSE|AUDIO, "audio_oss_out: got %d samples, vpts=%d pts=%d\n",
- num_samples, vpts,pts_);
-
- if (vpts<this->last_audio_vpts) {
- /* reject this */
- xprintf (VERBOSE|AUDIO, "audio_oss_out: rejected sample vpts=%d, last_audio_vpts=%d\n", vpts,this->last_audio_vpts)
-
- return 1;
- }
-
- this->last_audio_vpts = vpts;
-
- bDropPackage = 0;
-
- if ( this->audio_has_realtime || !this->audio_started ) {
-
- /*
- * where, in the timeline is the "end" of the audio buffer at the moment?
- */
-
- buffer_vpts = this->metronom->get_current_time (this->metronom);
-
- if (this->audio_started) {
- ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info);
- pos = info.bytes;
- } else
- pos = 0;
-
- if (pos>this->bytes_in_buffer) /* buffer ran dry */
- this->bytes_in_buffer = pos;
-
- buffer_vpts += (this->bytes_in_buffer - pos) * 1024 / this->bytes_per_kpts;
-
- /*
- * calculate gap:
- */
-
- gap = vpts - buffer_vpts;
- xprintf (VERBOSE|AUDIO, "audio_oss_out: buff=%d pos=%d buf_vpts=%d gap=%d\n",
- this->bytes_in_buffer, pos,buffer_vpts,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;
- xprintf (VERBOSE|AUDIO, "audio_oss_out: audio package (vpts = %d %d)"
- "dropped\n", vpts, gap);
- }
-
- } /* has realtime */
-
- /*
- * resample and output samples
- */
- if(this->mode == AO_CAP_MODE_AC3) bDropPackage=0;
-
- if (!bDropPackage) {
- int num_output_samples = num_samples * (this->output_sample_rate) / this->input_sample_rate;
-
- if (!this->do_resample) {
- write(this->audio_fd, output_samples,
- num_output_samples * this->num_channels * 2);
- } else switch (this->mode) {
- case AO_CAP_MODE_MONO:
- audio_out_resample_mono (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->sample_buffer, num_output_samples * 2);
- break;
- case AO_CAP_MODE_STEREO:
- audio_out_resample_stereo (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->sample_buffer, num_output_samples * 4);
- break;
- case AO_CAP_MODE_4CHANNEL:
- audio_out_resample_4channel (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->sample_buffer, num_output_samples * 8);
- break;
- case AO_CAP_MODE_5CHANNEL:
- audio_out_resample_5channel (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->sample_buffer, num_output_samples * 10);
- break;
- case AO_CAP_MODE_5_1CHANNEL:
- audio_out_resample_6channel (output_samples, num_samples,
- this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->sample_buffer, num_output_samples * 12);
- break;
- case AO_CAP_MODE_AC3:
- num_output_samples = num_samples+8;
- this->sample_buffer[0] = 0xf872; //spdif syncword
- this->sample_buffer[1] = 0x4e1f; // .............
- this->sample_buffer[2] = 0x0001; // AC3 data
- this->sample_buffer[3] = num_samples * 8;
-// this->sample_buffer[4] = 0x0b77; // AC3 syncwork already in output_samples
-
- // ac3 seems to be swabbed data
- swab(output_samples,this->sample_buffer+4, num_samples );
- write(this->audio_fd, this->sample_buffer, num_output_samples);
- write(this->audio_fd, this->zero_space, 6144-num_output_samples);
- num_output_samples=num_output_samples/4;
- break;
- }
-
- xprintf (AUDIO|VERBOSE, "audio_oss_out :audio package written\n");
-
- /*
- * step values
- */
-
- this->bytes_in_buffer += num_output_samples * 2 * this->num_channels;
- this->audio_started = 1;
- }
-
- return 1;
-
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ return self->bytes_per_frame;
}
+static int ao_oss_delay(ao_driver_t *self_gen)
+{
+ count_info info;
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ ioctl (self->audio_fd, SNDCTL_DSP_GETOPTR, &info);
+ return info.bytes / self->bytes_per_frame;
+}
-static void ao_close(ao_functions_t *this_gen)
+ /* Write audio samples
+ * num_frames is the number of audio frames present
+ * audio frames are equivalent one sample on each channel.
+ * I.E. Stereo 16 bits audio frames are 4 bytes.
+ */
+static int ao_oss_write(ao_driver_t *self_gen,
+ int16_t* frame_buffer, uint32_t num_frames)
{
- oss_functions_t *this = (oss_functions_t *) this_gen;
- close(this->audio_fd);
- this->audio_fd = -1;
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ return write(self->audio_fd, frame_buffer, num_frames * self->bytes_per_frame);
+
}
-static uint32_t ao_get_capabilities (ao_functions_t *this_gen) {
- oss_functions_t *this = (oss_functions_t *) this_gen;
- return this->capabilities;
+static void ao_oss_close(ao_driver_t *self_gen)
+{
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ close(self->audio_fd);
+ self->audio_fd = -1;
}
-static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) {
- oss_functions_t *this = (oss_functions_t *) this_gen;
-
- this->metronom = metronom;
+static uint32_t ao_oss_get_capabilities (ao_driver_t *self_gen) {
+ oss_driver_t *self = (oss_driver_t *) self_gen;
+ return self->capabilities;
}
-static void ao_exit(ao_functions_t *this_gen)
+static void ao_oss_exit(ao_driver_t *self_gen)
{
- oss_functions_t *this = (oss_functions_t *) this_gen;
+ oss_driver_t *self = (oss_driver_t *) self_gen;
- if (this->audio_fd != -1)
- close(this->audio_fd);
+ if (self->audio_fd != -1)
+ close(self->audio_fd);
- free (this->sample_buffer);
- free (this->zero_space);
- free (this);
+ free (self);
}
/*
*
*/
-static int ao_get_property (ao_functions_t *this, int property) {
+static int ao_oss_get_property (ao_driver_t *self_gen, int property) {
+ oss_driver_t *self = (oss_driver_t *) self;
/* FIXME: implement some properties
switch(property) {
@@ -517,7 +359,8 @@ 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_oss_set_property (ao_driver_t *self_gen, int property, int value) {
+ oss_driver_t *self = (oss_driver_t *) self;
/* FIXME: Implement property support.
switch(property) {
@@ -533,9 +376,9 @@ 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) {
- oss_functions_t *this;
+ oss_driver_t *self;
int caps;
#ifdef CONFIG_DEVFS_FS
char devname[] = "/dev/sound/dsp\0\0\0";
@@ -548,7 +391,7 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
int audio_fd;
int num_channels, status, arg;
- this = (oss_functions_t *) malloc (sizeof (oss_functions_t));
+ self = (oss_driver_t *) malloc (sizeof (oss_driver_t));
/*
* find best device driver/channel
@@ -561,11 +404,11 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
devnum = config->lookup_int (config, "oss_device_num", -1);
if (devnum >= 0) {
- sprintf (this->audio_dev, DSP_TEMPLATE, devnum);
+ sprintf (self->audio_dev, DSP_TEMPLATE, devnum);
devnum = 30; /* skip while loop */
} else {
devnum = 0;
- sprintf (this->audio_dev, "/dev/dsp");
+ sprintf (self->audio_dev, "/dev/dsp");
}
while (devnum<16) {
@@ -579,14 +422,14 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
rate = 48000;
ioctl(audio_fd,SNDCTL_DSP_SPEED, &rate);
if (rate>best_rate) {
- strncpy (this->audio_dev, devname, 19);
+ strncpy (self->audio_dev, devname, 19);
best_rate = rate;
}
close (audio_fd);
} /*else
printf("audio_oss_out: opening audio device %s failed:\n%s\n",
- this->audio_dev, strerror(errno));
+ self->audio_dev, strerror(errno));
*/
sprintf(devname, DSP_TEMPLATE, devnum);
@@ -597,18 +440,18 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
* open that device
*/
- audio_fd=open(this->audio_dev, O_WRONLY|O_NDELAY);
+ audio_fd=open(self->audio_dev, O_WRONLY|O_NDELAY);
if(audio_fd < 0)
{
printf("audio_oss_out: opening audio device %s failed:\n%s\n",
- this->audio_dev, strerror(errno));
+ self->audio_dev, strerror(errno));
- free (this);
+ free (self);
return NULL;
} else
- xprintf (VERBOSE|AUDIO, " %s\n", this->audio_dev);
+ xprintf (VERBOSE|AUDIO, " %s\n", self->audio_dev);
/*
* set up driver to reasonable values for capabilities tests
@@ -627,38 +470,38 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
if ((caps & DSP_CAP_REALTIME) > 0) {
xprintf (VERBOSE|AUDIO, "audio_oss_out : realtime check: passed :-)\n");
- this->audio_has_realtime = 1;
+ self->audio_has_realtime = 1;
} else {
printf ("audio_oss_out : realtime check: *FAILED* :-(((((\n");
- this->audio_has_realtime = 0;
+ self->audio_has_realtime = 0;
}
- if( !this->audio_has_realtime ) {
+ if( !self->audio_has_realtime ) {
printf("audio_oss_out: Audio driver realtime sync disabled...\n");
printf("audio_oss_out: ...Will use video master clock for soft-sync instead\n");
printf("audio_oss_out: ...There may be audio/video synchronization issues\n");
}
- this->capabilities = 0;
+ self->capabilities = 0;
printf ("audio_oss_out : supported modes are ");
num_channels = 1;
status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==1) ) {
- this->capabilities |= AO_CAP_MODE_MONO;
+ self->capabilities |= AO_CAP_MODE_MONO;
printf ("mono ");
}
num_channels = 2;
status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==2) ) {
- this->capabilities |= AO_CAP_MODE_STEREO;
+ self->capabilities |= AO_CAP_MODE_STEREO;
printf ("stereo ");
}
num_channels = 4;
status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==4) ) {
if (config->lookup_int (config, "four_channel", 0)) {
- this->capabilities |= AO_CAP_MODE_4CHANNEL;
+ self->capabilities |= AO_CAP_MODE_4CHANNEL;
printf ("4-channel ");
} else
printf ("(4-channel not enabled in .xinerc) " );
@@ -667,7 +510,7 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==5) ) {
if (config->lookup_int (config, "five_channel", 0)) {
- this->capabilities |= AO_CAP_MODE_5CHANNEL;
+ self->capabilities |= AO_CAP_MODE_5CHANNEL;
printf ("5-channel ");
} else
printf ("(5-channel not enabled in .xinerc) " );
@@ -676,7 +519,7 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==6) ) {
if (config->lookup_int (config, "five_lfe_channel", 0)) {
- this->capabilities |= AO_CAP_MODE_5_1CHANNEL;
+ self->capabilities |= AO_CAP_MODE_5_1CHANNEL;
printf ("5.1-channel ");
} else
printf ("(5.1-channel not enabled in .xinerc) " );
@@ -685,7 +528,7 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
ioctl(audio_fd,SNDCTL_DSP_GETFMTS,&caps);
if (caps & AFMT_AC3) {
if (config->lookup_int (config, "ac3_pass_through", 0)) {
- this->capabilities |= AO_CAP_MODE_AC3;
+ self->capabilities |= AO_CAP_MODE_AC3;
printf ("ac3-pass-through ");
} else
printf ("(ac3-pass-through not enabled in .xinerc)");
@@ -695,26 +538,21 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
close (audio_fd);
- this->resample_conf = config->lookup_int (config, "oss_resample", 0);
-
- this->output_sample_rate = 0;
- this->audio_fd = -1;
-
- this->sample_buffer = malloc (40000);
- memset (this->sample_buffer, 0, 40000);
- this->zero_space = malloc (ZERO_BUF_SIZE);
- memset (this->zero_space, 0, ZERO_BUF_SIZE);
-
- 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->output_sample_rate = 0;
+ self->audio_fd = -1;
+
+ self->ao_driver.get_capabilities = ao_oss_get_capabilities;
+ self->ao_driver.get_property = ao_oss_get_property;
+ self->ao_driver.set_property = ao_oss_set_property;
+ self->ao_driver.open = ao_oss_open;
+ self->ao_driver.num_channels = ao_oss_num_channels;
+ self->ao_driver.bytes_per_frame = ao_oss_bytes_per_frame;
+ self->ao_driver.delay = ao_oss_delay;
+ self->ao_driver.write = ao_oss_write;
+ self->ao_driver.close = ao_oss_close;
+ self->ao_driver.exit = ao_oss_exit;
+
+ return &self->ao_driver;
}
static ao_info_t ao_info_oss = {
diff --git a/src/libac3/xine_decoder.c b/src/libac3/xine_decoder.c
index c7ec83c35..6bd357f04 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.22 2001/08/02 14:35:58 joachim_koenig Exp $
+ * $Id: xine_decoder.c,v 1.23 2001/08/21 19:39:50 jcdutton Exp $
*
* stuff needed to turn libac3 into a xine decoder plugin
*/
@@ -69,7 +69,7 @@ typedef struct ac3dec_decoder_s {
sample_t delay[6*256];
sample_t samples[6][256];
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
int audio_caps;
int bypass_mode;
int output_sampling_rate;
@@ -83,7 +83,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) {
+void ac3dec_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
ac3dec_decoder_t *this = (ac3dec_decoder_t *) this_gen;
/* int i; */
@@ -303,7 +303,7 @@ static void ac3dec_decode_frame (ac3dec_decoder_t *this, uint32_t pts) {
/* output decoded samples */
- this->audio_out->write_audio_data (this->audio_out,
+ this->audio_out->write (this->audio_out,
this->int_samples,
256*6,
pts);
@@ -328,7 +328,7 @@ static void ac3dec_decode_frame (ac3dec_decoder_t *this, uint32_t pts) {
}
if (this->output_open) {
- this->audio_out->write_audio_data (this->audio_out,
+ this->audio_out->write (this->audio_out,
(int16_t*)this->frame_buffer,
this->frame_length,
pts);
diff --git a/src/liblpcm/xine_decoder.c b/src/liblpcm/xine_decoder.c
index 59644f339..6ce388884 100644
--- a/src/liblpcm/xine_decoder.c
+++ b/src/liblpcm/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.1 2001/08/04 20:14:54 guenter Exp $
+ * $Id: xine_decoder.c,v 1.2 2001/08/21 19:39:50 jcdutton Exp $
*
* stuff needed to turn libac3 into a xine decoder plugin
*/
@@ -42,7 +42,7 @@ typedef struct lpcm_decoder_s {
uint32_t pts;
uint32_t last_pts;
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
int output_open;
} lpcm_decoder_t;
@@ -52,7 +52,7 @@ int lpcm_can_handle (audio_decoder_t *this_gen, int buf_type) {
}
-void lpcm_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
+void lpcm_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen;
@@ -87,7 +87,7 @@ void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
for(i=0; i<buf->size/2; i++)
p[i] = ntohs(p[i]);
- this->audio_out->write_audio_data (this->audio_out,
+ this->audio_out->write (this->audio_out,
buf->content,
buf->size/4,
this->pts);
diff --git a/src/libmad/xine_decoder.c b/src/libmad/xine_decoder.c
index d79a4f57e..96f728e58 100644
--- a/src/libmad/xine_decoder.c
+++ b/src/libmad/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.1 2001/08/12 02:57:55 guenter Exp $
+ * $Id: xine_decoder.c,v 1.2 2001/08/21 19:39:50 jcdutton Exp $
*
* stuff needed to turn libmad into a xine decoder plugin
*/
@@ -43,7 +43,7 @@ typedef struct mad_decoder_s {
struct mad_stream stream;
struct mad_frame frame;
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
int output_sampling_rate;
int output_open;
@@ -59,7 +59,7 @@ static int mad_can_handle (audio_decoder_t *this_gen, int buf_type) {
}
-static void mad_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
+static void mad_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
mad_decoder_t *this = (mad_decoder_t *) this_gen;
@@ -193,7 +193,7 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
}
- this->audio_out->write_audio_data (this->audio_out,
+ this->audio_out->write (this->audio_out,
this->samples,
pcm->length,
buf->PTS);
diff --git a/src/libmpg123/interface.c b/src/libmpg123/interface.c
index 199c89479..45c78c604 100644
--- a/src/libmpg123/interface.c
+++ b/src/libmpg123/interface.c
@@ -18,7 +18,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: interface.c,v 1.4 2001/05/27 23:48:12 guenter Exp $
+ * $Id: interface.c,v 1.5 2001/08/21 19:39:50 jcdutton Exp $
*/
#include <stdlib.h>
@@ -40,7 +40,7 @@ void mpg_audio_reset (mpgaudio_t *mp) {
mp->header = 0;
}
-mpgaudio_t *mpg_audio_init (ao_functions_t *ao_output)
+mpgaudio_t *mpg_audio_init (ao_instance_t *ao_output)
{
mpgaudio_t *mp;
diff --git a/src/libmpg123/layer1.c b/src/libmpg123/layer1.c
index 4db905947..50a333a0e 100644
--- a/src/libmpg123/layer1.c
+++ b/src/libmpg123/layer1.c
@@ -157,7 +157,7 @@ void do_layer1(mpgaudio_t *mp)
printf ("layer1\n");
}
- mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
+ mp->ao_output->write (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
mp->pts);
mp->pts = 0;
diff --git a/src/libmpg123/layer2.c b/src/libmpg123/layer2.c
index c4230ad5d..b5a3c27b6 100644
--- a/src/libmpg123/layer2.c
+++ b/src/libmpg123/layer2.c
@@ -295,7 +295,7 @@ void do_layer2(mpgaudio_t *mp)
mp->sample_rate_device = fr->sample_rate;
}
- mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
+ mp->ao_output->write (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
mp->pts);
mp->pts = 0;
diff --git a/src/libmpg123/layer3.c b/src/libmpg123/layer3.c
index 08e444d69..db99e8fa6 100644
--- a/src/libmpg123/layer3.c
+++ b/src/libmpg123/layer3.c
@@ -1629,7 +1629,7 @@ void do_layer3(mpgaudio_t *mp)
mp->sample_rate_device = fr->sample_rate;
}
- mp->ao_output->write_audio_data (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
+ mp->ao_output->write (mp->ao_output, (int16_t*)mp->osspace, num_bytes/(stereo-1 ? 4:2),
mp->pts);
}
mp->pts = 0;
diff --git a/src/libmpg123/mpglib.h b/src/libmpg123/mpglib.h
index 0b06eee60..60014828f 100644
--- a/src/libmpg123/mpglib.h
+++ b/src/libmpg123/mpglib.h
@@ -18,7 +18,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: mpglib.h,v 1.5 2001/08/07 14:15:04 guenter Exp $
+ * $Id: mpglib.h,v 1.6 2001/08/21 19:39:50 jcdutton Exp $
*/
#ifndef HAVE_MPGLIB_H
@@ -48,7 +48,7 @@ typedef struct mpstr {
int is_output_initialized;
int sample_rate_device;
- ao_functions_t *ao_output;
+ ao_instance_t *ao_output;
unsigned char osspace[8192];
uint32_t pts;
@@ -62,7 +62,7 @@ typedef struct mpstr {
extern "C" {
#endif
-mpgaudio_t *mpg_audio_init (ao_functions_t *ao_output);
+mpgaudio_t *mpg_audio_init (ao_instance_t *ao_output);
void mpg_audio_reset (mpgaudio_t *mp);
diff --git a/src/libmpg123/xine_decoder.c b/src/libmpg123/xine_decoder.c
index 61c5c7d0d..649c51526 100644
--- a/src/libmpg123/xine_decoder.c
+++ b/src/libmpg123/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.4 2001/08/07 14:15:04 guenter Exp $
+ * $Id: xine_decoder.c,v 1.5 2001/08/21 19:39:50 jcdutton Exp $
*
* stuff needed to turn libmpg123 into a xine decoder plugin
*/
@@ -44,7 +44,7 @@ typedef struct mpgdec_decoder_s {
mpgaudio_t *mpg;
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
int output_sampling_rate;
int output_open;
@@ -55,7 +55,7 @@ int mpgdec_can_handle (audio_decoder_t *this_gen, int buf_type) {
}
-void mpgdec_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
+void mpgdec_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
mpgdec_decoder_t *this = (mpgdec_decoder_t *) this_gen;
diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c
index 7bb7ab461..69abf2e9f 100644
--- a/src/libw32dll/w32codec.c
+++ b/src/libw32dll/w32codec.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: w32codec.c,v 1.15 2001/08/06 13:21:26 ehasenle Exp $
+ * $Id: w32codec.c,v 1.16 2001/08/21 19:39:50 jcdutton Exp $
*
* routines for using w32 codecs
*
@@ -63,7 +63,7 @@ typedef struct w32v_decoder_s {
typedef struct w32a_decoder_s {
audio_decoder_t audio_decoder;
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
int decoder_ok;
unsigned char buf[16384];
@@ -404,7 +404,7 @@ static char* get_auds_codec_name(w32a_decoder_t *this, int id){
return NULL;
}
-static void w32a_init (audio_decoder_t *this_gen, ao_functions_t *audio_out) {
+static void w32a_init (audio_decoder_t *this_gen, ao_instance_t *audio_out) {
w32a_decoder_t *this = (w32a_decoder_t *) this_gen;
@@ -523,7 +523,7 @@ static void w32a_decode_audio (w32a_decoder_t *this,
this->sample_buf[0], this->sample_buf[1], this->sample_buf[2], this->sample_buf[3],
this->sample_buf[ash.cbDstLengthUsed-2], this->sample_buf[ash.cbDstLengthUsed-1]);
*/
- this->audio_out->write_audio_data (this->audio_out,
+ this->audio_out->write (this->audio_out,
(int16_t*) this->sample_buf,
ash.cbDstLengthUsed / (this->num_channels*2),
nPTS);
diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am
index c71bc26fe..0448aba9d 100644
--- a/src/xine-engine/Makefile.am
+++ b/src/xine-engine/Makefile.am
@@ -10,7 +10,7 @@ lib_LTLIBRARIES = libxine.la
libxine_la_SOURCES = xine.c metronom.c configfile.c buffer.c monitor.c \
utils.c load_plugins.c video_decoder.c \
- audio_decoder.c video_out.c events.c
+ audio_decoder.c video_out.c audio_out.c resample.c events.c
libxine_la_LIBADD = cpu_accel.lo \
$(THREAD_LIBS) \
$(DYNAMIC_LD_LIBS) \
@@ -20,7 +20,7 @@ libxine_la_LDFLAGS = -version-info 5:0:5
include_HEADERS = buffer.h metronom.h configfile.h \
monitor.h cpu_accel.h attributes.h utils.h \
- audio_out.h video_out.h xine_internal.h spu_decoder.h \
+ audio_out.h resample.h video_out.h xine_internal.h spu_decoder.h \
events.h
noinst_HEADERS = bswap.h
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
new file mode 100644
index 000000000..19273fdfd
--- /dev/null
+++ b/src/xine-engine/audio_out.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2000, 2001 the xine project
+ *
+ * This file is part of xine, a unix video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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 $
+ *
+ * 20-8-2001 First implementation of Audio sync and Audio driver separation.
+ * Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk
+ *
+ * General Programming Guidelines: -
+ * New concept of an "audio_frame".
+ * An audio_frame consists of all the samples required to fill every audio channel to a full amount of bits.
+ * So, it does not mater how many bits per sample, or how many audio channels are being used, the number of audio_frames is the same.
+ * E.g. 16 bit stereo is 4 bytes, but one frame.
+ * 16 bit 5.1 surround is 12 bytes, but one frame.
+ * The purpose of this is to make the audio_sync code a lot more readable, rather than having to multiply by the amount of channels all the time
+ * 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.
+ */
+
+/* required for swab() */
+#define _XOPEN_SOURCE 500
+/* required for FNDELAY decl */
+#define _BSD_SOURCE 1
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include <unistd.h>
+#if defined(__OpenBSD__)
+#include <soundcard.h>
+#elif defined(__FreeBSD__)
+#include <machine/soundcard.h>
+#else
+#if defined(__linux__)
+#include <linux/config.h> /* Check for DEVFS */
+#endif
+#include <sys/soundcard.h>
+#endif
+#include <sys/ioctl.h>
+#include <inttypes.h>
+
+#include "xine_internal.h"
+#include "monitor.h"
+#include "audio_out.h"
+#include "resample.h"
+#include "metronom.h"
+#include "utils.h"
+
+#ifndef AFMT_S16_NE
+# if defined(sparc) || defined(__sparc__) || defined(PPC)
+/* Big endian machines */
+# define AFMT_S16_NE AFMT_S16_BE
+# else
+# define AFMT_S16_NE AFMT_S16_LE
+# endif
+#endif
+
+#ifndef AFMT_AC3
+# define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */
+#endif
+
+#define AO_OUT_OSS_IFACE_VERSION 1
+
+#define AUDIO_NUM_FRAGMENTS 15
+#define AUDIO_FRAGMENT_SIZE 8192
+
+/* bufsize must be a multiple of 3 and 5 for 5.0 and 5.1 channel playback! */
+#define ZERO_BUF_SIZE 15360
+
+#define GAP_TOLERANCE 5000
+#define MAX_GAP 90000
+
+#ifdef CONFIG_DEVFS_FS
+#define DSP_TEMPLATE "/dev/sound/dsp%d"
+#else
+#define DSP_TEMPLATE "/dev/dsp%d"
+#endif
+
+/*
+ * open the audio device for writing to
+ */
+static int ao_open(ao_instance_t *self,
+ uint32_t bits, uint32_t rate, int mode)
+{
+ int result;
+ if(result=self->driver->open(self->driver,bits,rate,mode)<0) {
+ printf("open failed!\n");
+ return -1;
+ };
+// self->frame_rate_factor = (double) self->output_frame_rate / (double) self->input_frame_rate;
+ self->mode = mode;
+ self->input_frame_rate = rate;
+ self->frames_in_buffer = 0;
+ self->audio_started = 0;
+ self->last_audio_vpts = 0;
+
+ self->output_frame_rate=rate;
+ self->num_channels = self->driver->num_channels(self->driver);
+
+ self->frame_rate_factor = (double) 1 / (double) 1;
+ 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;
+ xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 frames\n", self->audio_step);
+
+ self->metronom->set_audio_rate(self->metronom, self->audio_step);
+
+
+ return 1;
+}
+
+static void ao_fill_gap (ao_instance_t *self, uint32_t pts_len) {
+
+ int num_bytes ;
+ xprintf (VERBOSE|AUDIO, "audio_out : fill_gap\n");
+
+ if (pts_len > MAX_GAP)
+ pts_len = MAX_GAP;
+ num_bytes = pts_len * self->frames_per_kpts / 1024;
+ num_bytes = (num_bytes / (2*self->num_channels)) * (2*self->num_channels);
+
+ if(self->mode == AO_CAP_MODE_AC3) return; /* FIXME */
+
+ printf ("audio_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len);
+
+ self->frames_in_buffer += num_bytes;
+
+ while (num_bytes > 0) {
+ if (num_bytes > ZERO_BUF_SIZE) {
+ self->driver->write(self->driver, self->zero_space, ZERO_BUF_SIZE);
+ num_bytes -= ZERO_BUF_SIZE;
+ } else {
+ self->driver->write(self->driver, self->zero_space, num_bytes);
+ num_bytes = 0;
+ }
+ }
+}
+
+
+
+static int ao_write(ao_instance_t *self,
+ int16_t* output_frames, uint32_t num_frames,
+ uint32_t pts_)
+{
+ uint32_t vpts, buffer_vpts;
+ int32_t gap;
+ int bDropPackage;
+ int pos;
+
+ if (self->driver<0)
+ return 1;
+
+ vpts = self->metronom->got_audio_samples (self->metronom, pts_, num_frames);
+
+ xprintf (VERBOSE|AUDIO, "audio_out: got %d frames, vpts=%d pts=%d\n",
+ num_frames, vpts,pts_);
+
+ if (vpts<self->last_audio_vpts) {
+ /* reject self */
+ xprintf (VERBOSE|AUDIO, "audio_out: rejected frame vpts=%d, last_audio_vpts=%d\n", vpts,self->last_audio_vpts)
+
+ return 1;
+ }
+
+ self->last_audio_vpts = vpts;
+
+ bDropPackage = 0;
+
+ if ( self->audio_has_realtime || !self->audio_started ) {
+
+ /*
+ * where, in the timeline is the "end" of the audio buffer at the moment?
+ */
+
+ buffer_vpts = self->metronom->get_current_time (self->metronom);
+
+ if (self->audio_started) {
+ pos = self->driver->delay(self->driver);
+ } else
+ pos = 0;
+ if ( (self->mode==AO_CAP_MODE_AC3) && (pos>10) ) pos-=10; /* External AC3 decoder delay correction */
+
+ if (pos>self->frames_in_buffer) /* buffer ran dry */
+ self->frames_in_buffer = pos;
+
+ buffer_vpts += (self->frames_in_buffer - pos) * 1024 / self->frames_per_kpts;
+
+ /*
+ * calculate gap:
+ */
+
+ gap = vpts - buffer_vpts;
+ xprintf (VERBOSE|AUDIO, "audio_out: buff=%d pos=%d buf_vpts=%d gap=%d\n",
+ self->frames_in_buffer, pos,buffer_vpts,gap);
+
+ if (gap>GAP_TOLERANCE) {
+ ao_fill_gap (self, gap);
+
+ /* keep xine responsive */
+
+ if (gap>MAX_GAP)
+ return 0;
+
+ } else if (gap<-GAP_TOLERANCE) {
+ bDropPackage = 1;
+ xprintf (VERBOSE|AUDIO, "audio_out: audio package (vpts = %d %d)"
+ "dropped\n", vpts, gap);
+ }
+
+ } /* has realtime */
+
+ /*
+ * resample and output frames
+ */
+ if(self->mode == AO_CAP_MODE_AC3) bDropPackage=0;
+
+ if (!bDropPackage) {
+ int num_output_frames = num_frames * (self->output_frame_rate) / self->input_frame_rate;
+
+ if ((!self->do_resample) && (self->mode != AO_CAP_MODE_AC3)) {
+ xprintf (VERBOSE|AUDIO, "audio_out: writing without resampling\n");
+ self->driver->write(self->driver, output_frames,
+ num_output_frames );
+ } else switch (self->mode) {
+ case AO_CAP_MODE_MONO:
+ audio_out_resample_mono (output_frames, num_frames,
+ self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_STEREO:
+ audio_out_resample_stereo (output_frames, num_frames,
+ self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ audio_out_resample_4channel (output_frames, num_frames,
+ self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_5CHANNEL:
+ audio_out_resample_5channel (output_frames, num_frames,
+ self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_5_1CHANNEL:
+ audio_out_resample_6channel (output_frames, num_frames,
+ self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ break;
+ case AO_CAP_MODE_AC3:
+ num_output_frames = (num_frames+8)/4;
+ 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
+
+ // ac3 seems to be swabbed data
+ swab(output_frames,self->frame_buffer+4, num_frames );
+ self->driver->write(self->driver, self->zero_space, 2); /* Prevents crackle at start. */
+ self->driver->write(self->driver, self->frame_buffer, num_output_frames);
+ self->driver->write(self->driver, self->zero_space, 1534-num_output_frames);
+ num_output_frames=num_output_frames;
+ break;
+ }
+
+ xprintf (AUDIO|VERBOSE, "audio_out :audio package written\n");
+
+ /*
+ * step values
+ */
+
+ self->frames_in_buffer += num_output_frames ;
+ self->audio_started = 1;
+ }
+
+ return 1;
+
+}
+
+
+static void ao_close(ao_instance_t *self)
+{
+ self->driver->close(self->driver);
+}
+
+static uint32_t ao_get_capabilities (ao_instance_t *self) {
+ uint32_t result;
+ result=self->driver->get_capabilities(self->driver);
+ return result;
+}
+
+ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom) {
+
+ ao_instance_t *self;
+
+ self = xmalloc (sizeof (ao_instance_t)) ;
+ self->driver = driver;
+ self->metronom = metronom;
+
+ self->open = ao_open;
+ self->write = ao_write;
+ self->close = ao_close;
+ self->get_capabilities = ao_get_capabilities;
+ self->audio_loop_running = 0;
+ self->frame_buffer = malloc (40000);
+ memset (self->frame_buffer, 0, 40000);
+ self->zero_space = malloc (ZERO_BUF_SIZE);
+ memset (self->zero_space, 0, ZERO_BUF_SIZE);
+ return self;
+}
+
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index c3e1fffbc..27b4c2f2d 100644
--- a/src/xine-engine/audio_out.h
+++ b/src/xine-engine/audio_out.h
@@ -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_out.h,v 1.8 2001/07/20 22:37:56 guenter Exp $
+ * $Id: audio_out.h,v 1.9 2001/08/21 19:39:50 jcdutton Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -37,13 +37,13 @@ extern "C" {
#define AUDIO_OUT_IFACE_VERSION 1
/*
- * ao_functions_s contains the functions every audio output
+ * ao_driver_s contains the driver every audio output
* driver plugin has to implement.
*/
-typedef struct ao_functions_s ao_functions_t;
+typedef struct ao_driver_s ao_driver_t;
-struct ao_functions_s {
+struct ao_driver_s {
/*
*
@@ -52,12 +52,7 @@ struct ao_functions_s {
*
* See AO_CAP_* bellow.
*/
- uint32_t (*get_capabilities) (ao_functions_t *this);
-
- /*
- * connect this driver to the xine engine
- */
- void (*connect) (ao_functions_t *this, metronom_t *metronom);
+ uint32_t (*get_capabilities) (ao_driver_t *this);
/*
* open the driver and make it ready to receive audio data
@@ -65,8 +60,21 @@ struct ao_functions_s {
*
* return value: <=0 : failure, 1 : ok
*/
+ int (*open)(ao_driver_t *this, uint32_t bits, uint32_t rate, int mode);
+
+ /* return the number of audio channels
+ */
+ int (*num_channels)(ao_driver_t *self_gen);
+
+ /* return the number of bytes per frame.
+ * A frame is equivalent to one sample being output on every audio channel.
+ */
+ int (*bytes_per_frame)(ao_driver_t *self_gen);
- int (*open)(ao_functions_t *this, uint32_t bits, uint32_t rate, int mode);
+ /* return the delay is frames measured by
+ * looking at pending samples in the audio output device
+ */
+ int (*delay)(ao_driver_t *self_gen);
/*
* write audio data to output buffer
@@ -76,24 +84,20 @@ struct ao_functions_s {
* 0 => audio samples were not yet processed,
* call write_audio_data with the _same_ samples again
*/
-
- int (*write_audio_data)(ao_functions_t *this,
- int16_t* audio_data, uint32_t num_samples,
- uint32_t pts);
+ int (*write)(ao_driver_t *this,
+ int16_t* audio_data, uint32_t num_samples);
/*
* this is called when the decoder no longer uses the audio
* output driver - the driver should get ready to get opened() again
*/
-
- void (*close)(ao_functions_t *this);
+ void (*close)(ao_driver_t *this);
/*
* shut down this audio output driver plugin and
* free all resources allocated
*/
-
- void (*exit) (ao_functions_t *this);
+ void (*exit) (ao_driver_t *this);
/*
* Get, Set a property of audio driver.
@@ -103,19 +107,82 @@ struct ao_functions_s {
*
* See AC_PROP_* bellow for available properties.
*/
- int (*get_property) (ao_functions_t *this, int property);
+ int (*get_property) (ao_driver_t *this, int property);
- int (*set_property) (ao_functions_t *this, int property, int value);
+ int (*set_property) (ao_driver_t *this, int property, int value);
};
+/*
+ * ao_instance_s contains the instance every audio decoder talks to
+ */
+typedef struct ao_instance_s ao_instance_t;
+
+struct ao_instance_s {
+ uint32_t (*get_capabilities) (ao_instance_t *this); /* for constants see below */
+
+ /* open display driver for video output */
+ int (*open) (ao_instance_t *this,
+ uint32_t bits, uint32_t rate, int mode);
+
+ /*
+ * write audio data to output buffer
+ * audio driver must sync sample playback with metronom
+ * return value:
+ * 1 => audio samples were processed ok
+ * 0 => audio samples were not yet processed,
+ * call write_audio_data with the _same_ samples again
+ */
+
+ int (*write)(ao_driver_t *this,
+ int16_t* audio_data, uint32_t num_frames,
+ uint32_t pts);
+
+ /* audio driver is no longer used by decoder => close */
+ void (*close) (ao_instance_t *self);
+
+ /* called on xine exit */
+ void (*exit) (ao_instance_t *this);
+
+ /* private stuff */
+
+ ao_driver_t *driver;
+ metronom_t *metronom;
+
+ int audio_loop_running;
+ pthread_t audio_thread;
+ int audio_step; /* pts per 32 768 samples (sample = #bytes/2) */
+ int32_t frames_per_kpts; /* bytes per 1024/90000 sec */
+ int32_t output_frame_rate, input_frame_rate;
+ double frame_rate_factor;
+ uint32_t num_channels;
+ uint32_t frames_in_buffer; /* a frame is equivalent to one sample in each channel. */
+ int audio_started;
+ int audio_has_realtime; /* OSS driver supports real-time */
+ uint32_t last_audio_vpts;
+ int resample_conf;
+ int do_resample;
+ int mode;
+ uint16_t *frame_buffer;
+ int16_t *zero_space;
+ int pts_per_half_frame;
+ int pts_per_frame;
+
+ int num_frames_delivered;
+ int num_frames_skipped;
+ int num_frames_discarded;
+};
+/* This initiates the audio_out sync routines
+ * found in ./src/xine-engine/audio_out.c
+ */
+ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom) ;
/*
* to build a dynamic audio output plugin,
- * you have to implement these functions:
+ * you have to implement these driver:
*
*
- * ao_functions_t *init_audio_out_plugin (config_values_t *config)
+ * ao_driver_t *init_audio_out_plugin (config_values_t *config)
*
* init this plugin, check if device is available
*
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index 619717545..56936d1a1 100644
--- a/src/xine-engine/load_plugins.c
+++ b/src/xine-engine/load_plugins.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: load_plugins.c,v 1.37 2001/08/14 01:38:17 guenter Exp $
+ * $Id: load_plugins.c,v 1.38 2001/08/21 19:39:50 jcdutton Exp $
*
*
* Load input/demux/audio_out/video_out/codec plugins
@@ -713,11 +713,11 @@ char **xine_list_audio_output_plugins(void) {
return plugin_ids;
}
-ao_functions_t *xine_load_audio_output_plugin(config_values_t *config,
+ao_driver_t *xine_load_audio_output_plugin(config_values_t *config,
char *id) {
DIR *dir;
- ao_functions_t *aod = NULL;
+ ao_driver_t *aod = NULL;
dir = opendir (XINE_PLUGINDIR);
@@ -757,7 +757,7 @@ ao_functions_t *xine_load_audio_output_plugin(config_values_t *config,
if((initplug = dlsym(plugin, "init_audio_out_plugin")) != NULL) {
- aod = (ao_functions_t *) initplug(config);
+ aod = (ao_driver_t *) initplug(config);
if (aod)
printf("load_plugins: audio output plugin %s successfully"
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
index 83d1e4ebe..17fd9385b 100644
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.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.c,v 1.44 2001/08/20 20:49:51 f1rmb Exp $
+ * $Id: xine.c,v 1.45 2001/08/21 19:39:50 jcdutton Exp $
*
* top-level xine functions
*
@@ -452,7 +452,7 @@ static void event_handler(xine_t *xine, event_t *event, void *data) {
}
xine_t *xine_init (vo_driver_t *vo,
- ao_functions_t *ao,
+ ao_driver_t *ao,
config_values_t *config,
gui_stream_end_cb_t stream_end_cb,
gui_get_next_mrl_cb_t get_next_mrl_cb,
@@ -515,8 +515,9 @@ xine_t *xine_init (vo_driver_t *vo,
video_decoder_init (this);
if(ao) {
- this->audio_out = ao;
- this->audio_out->connect (this->audio_out, this->metronom);
+ this->audio_out = ao_new_instance (ao, this->metronom);
+// this->audio_out = ao;
+// this->audio_out->connect (this->audio_out, this->metronom);
}
audio_decoder_init (this);
printf("xine_init returning\n");
diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h
index 13fc9803b..8c91426e6 100644
--- a/src/xine-engine/xine_internal.h
+++ b/src/xine-engine/xine_internal.h
@@ -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_internal.h,v 1.38 2001/08/17 16:15:37 f1rmb Exp $
+ * $Id: xine_internal.h,v 1.39 2001/08/21 19:39:50 jcdutton Exp $
*
*/
@@ -93,7 +93,7 @@ struct audio_decoder_s {
int (*can_handle) (audio_decoder_t *this, int buf_type);
- void (*init) (audio_decoder_t *this, ao_functions_t *audio_out);
+ void (*init) (audio_decoder_t *this, ao_instance_t *audio_out);
void (*decode_data) (audio_decoder_t *this, buf_element_t *buf);
@@ -167,7 +167,7 @@ struct xine_s {
video_decoder_t *cur_video_decoder_plugin;
int video_finished;
- ao_functions_t *audio_out;
+ ao_instance_t *audio_out;
fifo_buffer_t *audio_fifo;
pthread_t audio_thread;
audio_decoder_t *audio_decoder_plugins[DECODER_PLUGIN_MAX];
@@ -202,7 +202,7 @@ config_values_t *config_file_init (char *filename);
*/
xine_t *xine_init (vo_driver_t *vo,
- ao_functions_t *ao,
+ ao_driver_t *ao,
config_values_t *config,
gui_stream_end_cb_t stream_end_cb,
gui_get_next_mrl_cb_t get_next_mrl_cb,
@@ -447,7 +447,7 @@ char **xine_list_audio_output_plugins ();
* load a specific audio output plugin
*/
-ao_functions_t *xine_load_audio_output_plugin(config_values_t *config, char *id);
+ao_driver_t *xine_load_audio_output_plugin(config_values_t *config, char *id);
/**
* @defgroup eventgroup Sending events