summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_out/Makefile.am9
-rw-r--r--src/audio_out/audio_esd_out.c364
-rw-r--r--src/audio_out/audio_oss_out.c37
3 files changed, 225 insertions, 185 deletions
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am
index ce40db822..5a65135c3 100644
--- a/src/audio_out/Makefile.am
+++ b/src/audio_out/Makefile.am
@@ -36,8 +36,7 @@ endif
# All of xine audio out plugins should be named like the
# scheme "xineplug_ao_out_"
#
-#lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) $(esd_module)
-lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) $(arts_module) #$(esd_module)
+lib_LTLIBRARIES = $(oss_module) $(alsa_module) $(sun_module) $(arts_module) $(esd_module)
xineplug_ao_out_oss_la_SOURCES = audio_oss_out.c resample.c
xineplug_ao_out_oss_la_LDFLAGS = -avoid-version -module
@@ -47,9 +46,9 @@ xineplug_ao_out_alsa_la_SOURCES = audio_alsa_out.c audio_alsa05_out.c \
xineplug_ao_out_alsa_la_LIBADD = $(ALSA_LIBS)
xineplug_ao_out_alsa_la_LDFLAGS = -avoid-version -module
-#xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c resample.c
-#xineplug_ao_out_esd_la_LIBADD = $(ESD_LIBS)
-#xineplug_ao_out_esd_la_LDFLAGS = -avoid-version -module
+xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c resample.c
+xineplug_ao_out_esd_la_LIBADD = $(ESD_LIBS)
+xineplug_ao_out_esd_la_LDFLAGS = -avoid-version -module
xineplug_ao_out_sun_la_SOURCES = audio_sun_out.c resample.c
xineplug_ao_out_sun_la_LDFLAGS = -avoid-version -module
diff --git a/src/audio_out/audio_esd_out.c b/src/audio_out/audio_esd_out.c
index f9409842a..baa4acded 100644
--- a/src/audio_out/audio_esd_out.c
+++ b/src/audio_out/audio_esd_out.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 the xine project
+ * Copyright (C) 2000, 2001 the xine project
*
* This file is part of xine, a unix video player.
*
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* 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_esd_out.c,v 1.4 2001/06/24 23:08:42 guenter Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -36,212 +38,198 @@
#include "audio_out.h"
#include "resample.h"
#include "metronom.h"
-#include "libac3/ac3.h"
#include "utils.h"
#define AO_OUT_ESD_IFACE_VERSION 1
+
+#define AUDIO_NUM_FRAGMENTS 15
+#define AUDIO_FRAGMENT_SIZE 8192
+
#define GAP_TOLERANCE 15000
-#define MAX_MASTER_CLOCK_DIV 5000
+#define MAX_GAP 90000
+
+typedef struct esd_functions_s {
-typedef struct _audio_esd_globals {
+ ao_functions_t ao_functions;
+
+ metronom_t *metronom;
int audio_fd;
+ int capabilities;
+ int mode;
int32_t output_sample_rate, input_sample_rate;
- int32_t output_rate_correction;
double sample_rate_factor;
uint32_t num_channels;
uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
- uint32_t last_vpts; /* vpts at which last written package ends */
-
- uint32_t sync_vpts; /* this syncpoint is used as a starting point */
- uint32_t sync_bytes_in_buffer; /* for vpts <-> samplecount assoc */
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;
+ uint32_t last_audio_vpts;
+
+ uint32_t latency;
-} audio_esd_globals_t;
+} esd_functions_t;
-static audio_esd_globals_t gAudioESD;
/*
- * open the audio device for writing to
+ * connect to esd
*/
-static int ao_open(metronom_t *metronom,
+static int ao_open(ao_functions_t *this_gen,
uint32_t bits, uint32_t rate, int mode)
{
- esd_format_t format;
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+ esd_format_t format;
- printf ("audio_esd_out: ao_open rate=%d, mode=%d\n", rate, mode);
+ printf ("audio_esd_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
- if ((mode != AO_MODE_STEREO) && (mode != AO_MODE_MONO)) {
- printf ("ESD Driver only supports mono/stereo output modes at the moment\n");
+ if ( (mode & this->capabilities) == 0 ) {
+ printf ("audio_esd_out: unsupported mode %08x\n", mode);
return -1;
}
- if (gAudioESD.audio_fd > -1) {
+ if (this->audio_fd>=0) {
- if (rate == gAudioESD.input_sample_rate)
+ if ( (mode == this->mode) && (rate == this->input_sample_rate) )
return 1;
- close (gAudioESD.audio_fd);
+ close (this->audio_fd);
}
-
- gAudioESD.input_sample_rate = rate;
- gAudioESD.bytes_in_buffer = 0;
- gAudioESD.last_vpts = 0;
- gAudioESD.output_rate_correction = 0;
- gAudioESD.sync_vpts = 0;
- gAudioESD.sync_bytes_in_buffer = 0;
- gAudioESD.audio_started = 0;
+
+ this->mode = mode;
+ this->input_sample_rate = rate;
+ this->bytes_in_buffer = 0;
+ this->audio_started = 0;
+ this->last_audio_vpts = 0;
+ this->output_sample_rate = rate;
/*
* open stream to ESD server
*/
format = ESD_STREAM | ESD_PLAY | ESD_BITS16;
- if (mode == AO_MODE_STEREO) {
- format |= ESD_STEREO;
- gAudioESD.num_channels = 2;
- } else {
+ switch (mode) {
+ case AO_CAP_MODE_MONO:
format |= ESD_MONO;
- gAudioESD.num_channels = 1;
+ this->num_channels = 1;
+ break;
+ case AO_CAP_MODE_STEREO:
+ format |= ESD_STEREO;
+ this->num_channels = 2;
+ break;
}
- gAudioESD.output_sample_rate = gAudioESD.input_sample_rate;
- if (gAudioESD.output_sample_rate > 44100)
- gAudioESD.output_sample_rate = 44100;
+ printf ("audio_esd_out: %d channels output\n",this->num_channels);
- gAudioESD.audio_fd=esd_play_stream(format, gAudioESD.output_sample_rate, NULL, NULL);
- if(gAudioESD.audio_fd < 0) {
- printf("audio_esd_out: Connecting to ESD server %s: %s\n",
+ if (this->output_sample_rate > 44100)
+ this->output_sample_rate = 44100;
+
+
+ this->audio_fd=esd_play_stream(format, this->output_sample_rate, NULL, NULL);
+ if (this->audio_fd < 0) {
+ printf("audio_esd_out: connecting to ESD server %s: %s\n",
getenv("ESPEAKER"), strerror(errno));
return -1;
}
- xprintf (VERBOSE|AUDIO, "audio_esd_out: %d channels\n",gAudioESD.num_channels);
-
- gAudioESD.sample_rate_factor = (double) gAudioESD.output_sample_rate / (double) gAudioESD.input_sample_rate;
- gAudioESD.audio_step = (uint32_t) 90000 * (uint32_t) 32768
- / gAudioESD.input_sample_rate;
- gAudioESD.bytes_per_kpts = gAudioESD.output_sample_rate * gAudioESD.num_channels * 2 * 1024 / 90000;
+ 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", gAudioESD.audio_step);
-
- metronom->set_audio_rate (metronom, gAudioESD.audio_step);
+ printf ("audio_out : audio_step %d pts per 32768 samples\n", this->audio_step);
return 1;
}
-static uint32_t ao_get_current_vpts (void) {
-
- int32_t diff ;
- uint32_t vpts ;
-
- if (gAudioESD.audio_started)
- diff = 0;
- else
- diff = gAudioESD.sync_bytes_in_buffer;
-
- vpts = gAudioESD.sync_vpts - diff * 1024 / gAudioESD.bytes_per_kpts;
-
-// xprintf (AUDIO|VERBOSE,"audio_esd_out: get_current_vpts pos=%d diff=%d vpts=%d sync_vpts=%d\n",
-// pos, diff, vpts, gAudioESD.sync_vpts);
-
- return vpts;
-}
+static void ao_fill_gap (esd_functions_t *this, uint32_t pts_len) {
-static void ao_fill_gap (uint32_t pts_len) {
+ int num_bytes ;
- int num_bytes = pts_len * gAudioESD.bytes_per_kpts / 1024;
-
- num_bytes = (num_bytes / 4) * 4;
+ 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);
printf ("audio_esd_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len);
- gAudioESD.bytes_in_buffer += num_bytes;
+ this->bytes_in_buffer += num_bytes;
while (num_bytes>0) {
if (num_bytes>8192) {
- write(gAudioESD.audio_fd, gAudioESD.zero_space, 8192);
+ write(this->audio_fd, this->zero_space, 8192);
num_bytes -= 8192;
} else {
- write(gAudioESD.audio_fd, gAudioESD.zero_space, num_bytes);
+ write(this->audio_fd, this->zero_space, num_bytes);
num_bytes = 0;
}
}
-
- gAudioESD.last_vpts += pts_len;
}
-static void ao_write_audio_data(metronom_t *metronom,
- int16_t* output_samples, uint32_t num_samples,
- uint32_t pts_)
+static int ao_write_audio_data(ao_functions_t *this_gen,
+ int16_t* output_samples, uint32_t num_samples,
+ uint32_t pts_)
{
- uint32_t vpts,
- audio_vpts,
- master_vpts;
- int32_t diff, gap;
- int bDropPackage;
- uint16_t sample_buffer[8192];
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+ uint32_t vpts, buffer_vpts;
+ int32_t gap;
+ int bDropPackage;
+ int pos;
-
- if (gAudioESD.audio_fd<0)
- return;
+ if (this->audio_fd<0)
+ return 1;
- vpts = metronom->got_audio_samples (metronom, pts_, num_samples);
+ vpts = this->metronom->got_audio_samples (this->metronom, pts_, num_samples);
- xprintf (VERBOSE|AUDIO, "audio_esd_out: got %d samples, vpts=%d, last_vpts=%d\n",
- num_samples, vpts, gAudioESD.last_vpts);
+ xprintf (VERBOSE|AUDIO, "audio_esd_out: got %d samples, vpts=%d\n",
+ num_samples, vpts);
- /*
- * check if these samples "fit" in the audio output buffer
- * or do we have an audio "gap" here?
- */
-
- gap = vpts - gAudioESD.last_vpts ;
-
- /*
- printf ("audio_esd_out: gap = %d - %d + %d = %d\n",
- vpts, gAudioESD.last_vpts, diff, gap);
- */
+ if (vpts<this->last_audio_vpts) {
+ /* reject this */
- bDropPackage = 0;
-
- if (gap>GAP_TOLERANCE) {
- ao_fill_gap (gap);
- } else if (gap<-GAP_TOLERANCE) {
- bDropPackage = 1;
+ return 1;
}
+ this->last_audio_vpts = vpts;
+
/*
- * sync on master clock
+ * where, in the timeline is the "end" of the audio buffer at the moment?
*/
- audio_vpts = ao_get_current_vpts () ;
- master_vpts = metronom->get_current_time (metronom);
- diff = audio_vpts - master_vpts;
+ buffer_vpts = this->metronom->get_current_time (this->metronom);
+
+ buffer_vpts += 3000; /* FIXME - esd doesn't have sync capabilities */
- xprintf (AUDIO|VERBOSE, "audio_esd_out: syncing on master clock: audio_vpts=%d master_vpts=%d\n",
- audio_vpts, master_vpts);
/*
- printf ("audio_esd_out: audio_vpts=%d <=> master_vpts=%d (diff=%d)\n",
- audio_vpts, master_vpts, diff);
+ printf ("audio_esd_out: got audio package vpts = %d, buffer_vpts = %d\n",
+ vpts, buffer_vpts);
*/
/*
- * adjust master clock
+ * calculate gap:
*/
- if (abs(diff)>MAX_MASTER_CLOCK_DIV) {
- printf ("master clock adjust time %d -> %d (diff: %d)\n", master_vpts, audio_vpts, diff);
- metronom->adjust_clock (metronom, audio_vpts);
+ gap = vpts - buffer_vpts;
+
+ bDropPackage = 0;
+
+ 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;
}
/*
@@ -249,65 +237,87 @@ static void ao_write_audio_data(metronom_t *metronom,
*/
if (!bDropPackage) {
- int num_output_samples = num_samples * (gAudioESD.output_sample_rate + gAudioESD.output_rate_correction) / gAudioESD.input_sample_rate;
-
-
- audio_out_resample_stereo (output_samples, num_samples,
- sample_buffer, num_output_samples);
-
- write(gAudioESD.audio_fd, sample_buffer, num_output_samples * 2 * gAudioESD.num_channels);
+ int num_output_samples = num_samples * (this->output_sample_rate) / this->input_sample_rate;
+
+ 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;
+ }
xprintf (AUDIO|VERBOSE, "audio_esd_out :audio package written\n");
/*
- * remember vpts
- */
-
- gAudioESD.sync_vpts = vpts;
- gAudioESD.sync_bytes_in_buffer = gAudioESD.bytes_in_buffer;
-
- /*
* step values
*/
- gAudioESD.bytes_in_buffer += num_output_samples * 2 * gAudioESD.num_channels;
- gAudioESD.audio_started = 1;
+ this->bytes_in_buffer += num_output_samples * 2 * this->num_channels;
+ this->audio_started = 1;
} else {
printf ("audio_esd_out: audio package (vpts = %d) dropped\n", vpts);
- gAudioESD.sync_vpts = vpts;
}
-
- gAudioESD.last_vpts = vpts + num_samples * 90000 / gAudioESD.input_sample_rate ;
-}
+ return 1;
+
+}
-static void ao_close(void)
+static void ao_close(ao_functions_t *this_gen)
{
- close(gAudioESD.audio_fd);
- gAudioESD.audio_fd = -1;
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+ esd_close(this->audio_fd);
+ this->audio_fd = -1;
}
-static int ao_is_mode_supported (int mode) {
- return ((mode == AO_MODE_STEREO) || (mode == AO_MODE_MONO));
+static uint32_t ao_get_capabilities (ao_functions_t *this_gen) {
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+ return this->capabilities;
}
-static char *ao_get_ident(void) {
- return "ESD";
+static void ao_connect (ao_functions_t *this_gen, metronom_t *metronom) {
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+
+ this->metronom = metronom;
}
-static ao_functions_t audio_esdout = {
- AO_OUT_ESD_IFACE_VERSION,
- ao_is_mode_supported,
- ao_open,
- ao_write_audio_data,
- ao_close,
- ao_get_ident
-};
+static void ao_exit(ao_functions_t *this_gen)
+{
+ esd_functions_t *this = (esd_functions_t *) this_gen;
+
+ if (this->audio_fd != -1)
+ esd_close(this->audio_fd);
+ free (this->sample_buffer);
+ free (this->zero_space);
+ free (this);
+}
-ao_functions_t *init_audio_out_plugin (int iface, config_values_t *config)
-{
- int audio_fd;
+static int ao_get_property (ao_functions_t *this, int property) {
+
+ /* FIXME: implement some properties
+ */
+ return 0;
+}
+
+static int ao_set_property (ao_functions_t *this, int property, int value) {
+
+ /* FIXME: Implement property support.
+ */
+
+ return ~value;
+}
+
+ao_functions_t *init_audio_out_plugin (config_values_t *config) {
+
+ esd_functions_t *this;
+ int caps;
+ int audio_fd;
/*
* open stream to ESD server
@@ -321,17 +331,45 @@ ao_functions_t *init_audio_out_plugin (int iface, config_values_t *config)
char *server = getenv("ESPEAKER");
// print a message so the user knows why ESD failed
- printf("Can't connect to %s ESD server: %s\n",
+ printf("audio_esd_out: can't connect to %s ESD server: %s\n",
server ? server : "local", strerror(errno));
return NULL;
- } // else
-// xprintf(VERBOSE|AUDIO, " %s\n", gAudioESD.audio_dev);
+ }
+
+ esd_close(audio_fd);
+
+
+ this = (esd_functions_t *) malloc (sizeof (esd_functions_t));
+ this->output_sample_rate = 0;
+ this->audio_fd = -1;
+ this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO;
- close(audio_fd);
+ this->sample_buffer = malloc (40000);
+ memset (this->sample_buffer, 0, 40000);
+ this->zero_space = malloc (8192);
+ memset (this->zero_space, 0, 8192);
- gAudioESD.output_sample_rate = 0;
- gAudioESD.zero_space = xmalloc (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 &audio_esdout;
+ return &this->ao_functions;
}
+
+static ao_info_t ao_info_esd = {
+ AUDIO_OUT_IFACE_VERSION,
+ "esd",
+ "xine audio output plugin using esd",
+ 1
+};
+
+ao_info_t *get_audio_out_plugin_info() {
+ return &ao_info_esd;
+}
+
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index bb8104f1d..095e6baa5 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.18 2001/06/24 07:17:37 guenter Exp $
+ * $Id: audio_oss_out.c,v 1.19 2001/06/24 23:08:42 guenter Exp $
*/
/* required for swab() */
@@ -103,6 +103,7 @@ typedef struct oss_functions_s {
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;
@@ -275,7 +276,6 @@ static int ao_write_audio_data(ao_functions_t *this_gen,
uint32_t vpts, buffer_vpts;
int32_t gap;
int bDropPackage;
- uint16_t sample_buffer[10000];
count_info info;
int pos;
@@ -348,35 +348,35 @@ static int ao_write_audio_data(ao_functions_t *this_gen,
switch (this->mode) {
case AO_CAP_MODE_MONO:
audio_out_resample_mono (output_samples, num_samples,
- sample_buffer, num_output_samples);
- write(this->audio_fd, sample_buffer, num_output_samples * 2);
+ 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,
- sample_buffer, num_output_samples);
- write(this->audio_fd, sample_buffer, num_output_samples * 4);
+ 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,
- sample_buffer, num_output_samples);
- write(this->audio_fd, sample_buffer, num_output_samples * 8);
+ 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,
- sample_buffer, num_output_samples);
- write(this->audio_fd, sample_buffer, num_output_samples * 10);
+ this->sample_buffer, num_output_samples);
+ write(this->audio_fd, this->sample_buffer, num_output_samples * 10);
break;
case AO_CAP_MODE_AC3:
num_output_samples = num_samples+8;
- sample_buffer[0] = 0xf872; //spdif syncword
- sample_buffer[1] = 0x4e1f; // .............
- sample_buffer[2] = 0x0001; // AC3 data
- sample_buffer[3] = num_samples * 8;
-// sample_buffer[4] = 0x0b77; // AC3 syncwork already in output_samples
+ 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,sample_buffer+4, num_samples );
- write(this->audio_fd, sample_buffer, num_output_samples);
+ 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;
@@ -424,6 +424,7 @@ static void ao_exit(ao_functions_t *this_gen)
if (this->audio_fd != -1)
close(this->audio_fd);
+ free (this->sample_buffer);
free (this->zero_space);
free (this);
}
@@ -604,6 +605,8 @@ ao_functions_t *init_audio_out_plugin (config_values_t *config) {
this->output_sample_rate = 0;
this->audio_fd = -1;
+ this->sample_buffer = malloc (40000);
+ memset (this->sample_buffer, 0, 40000);
this->zero_space = malloc (8192);
memset (this->zero_space, 0, 8192);