diff options
-rw-r--r-- | src/audio_out/Makefile.am | 9 | ||||
-rw-r--r-- | src/audio_out/audio_esd_out.c | 364 | ||||
-rw-r--r-- | src/audio_out/audio_oss_out.c | 37 |
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); |