diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-08-23 21:40:05 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-08-23 21:40:05 +0000 |
commit | 9af0f9b8e5cf19ac23ddf3e1ff62629b0109d253 (patch) | |
tree | f675c9458bb600f1b0c7843e882b1263f84083c9 | |
parent | d08d8d6d67096518a67a3cd4467d3c0b1186d3e8 (diff) | |
download | xine-lib-9af0f9b8e5cf19ac23ddf3e1ff62629b0109d253.tar.gz xine-lib-9af0f9b8e5cf19ac23ddf3e1ff62629b0109d253.tar.bz2 |
re-enabled audio resampling, correct a/v sync, corrected code style/indentation. corrected delay() behaviour according to what's specified in the header file comment: return delay(offset) instead of absolute time
CVS patchset: 473
CVS date: 2001/08/23 21:40:05
-rw-r--r-- | src/audio_out/audio_oss_out.c | 255 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 353 | ||||
-rw-r--r-- | src/xine-engine/audio_out.h | 55 | ||||
-rw-r--r-- | src/xine-engine/xine.c | 4 | ||||
-rw-r--r-- | src/xine-engine/xine_internal.h | 4 |
5 files changed, 345 insertions, 326 deletions
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c index 82227e5b2..76abc62e8 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.31 2001/08/22 10:51:05 jcdutton Exp $ + * $Id: audio_oss_out.c,v 1.32 2001/08/23 21:40:05 guenter Exp $ * * 20-8-2001 First implementation of Audio sync and Audio driver separation. * Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk @@ -32,7 +32,7 @@ * 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() */ @@ -110,7 +110,6 @@ typedef struct oss_driver_s { int mode; 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; @@ -118,52 +117,53 @@ typedef struct oss_driver_s { int audio_started; int audio_has_realtime; /* OSS driver supports real-time */ + int static_delay; /* estimated delay for non-realtime drivers */ } oss_driver_t; /* * open the audio device for writing to */ -static int ao_oss_open(ao_driver_t *self_gen, - uint32_t bits, uint32_t rate, int mode) +static int ao_oss_open(ao_driver_t *this_gen, + uint32_t bits, uint32_t rate, int mode) { - oss_driver_t *self = (oss_driver_t *) self_gen; + oss_driver_t *this = (oss_driver_t *) this_gen; int tmp; printf ("audio_oss_out: ao_open rate=%d, mode=%d\n", rate, mode); - if ( (mode & self->capabilities) == 0 ) { + if ( (mode & this->capabilities) == 0 ) { printf ("audio_oss_out: unsupported mode %08x\n", mode); - return -1; + return 0; } - if (self->audio_fd > -1) { + if (this->audio_fd > -1) { - if ( (mode == self->mode) && (rate == self->input_sample_rate) ) { - return 1; + if ( (mode == this->mode) && (rate == this->input_sample_rate) ) { + return this->output_sample_rate; } - close (self->audio_fd); + close (this->audio_fd); } - self->mode = mode; - self->input_sample_rate = rate; - self->bits_per_sample = bits; - self->bytes_in_buffer = 0; - self->audio_started = 0; + this->mode = mode; + this->input_sample_rate = rate; + this->bits_per_sample = bits; + this->bytes_in_buffer = 0; + this->audio_started = 0; /* * open audio device */ - self->audio_fd=open(self->audio_dev,O_WRONLY|O_NDELAY); - if(self->audio_fd < 0) { + this->audio_fd=open(this->audio_dev,O_WRONLY|O_NDELAY); + if(this->audio_fd < 0) { printf("audio_oss_out: Opening audio device %s: %s\n", - self->audio_dev, strerror(errno)); - return -1; + this->audio_dev, strerror(errno)); + return 0; } /* We wanted non blocking open but now put it back to normal */ - fcntl(self->audio_fd, F_SETFL, fcntl(self->audio_fd, F_GETFL)&~FNDELAY); + fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL)&~FNDELAY); /* * configure audio device @@ -171,29 +171,29 @@ static int ao_oss_open(ao_driver_t *self_gen, */ if(!(mode & AO_CAP_MODE_AC3)) { tmp = (mode & AO_CAP_MODE_STEREO) ? 1 : 0; - ioctl(self->audio_fd,SNDCTL_DSP_STEREO,&tmp); + ioctl(this->audio_fd,SNDCTL_DSP_STEREO,&tmp); tmp = bits; - ioctl(self->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp); + ioctl(this->audio_fd,SNDCTL_DSP_SAMPLESIZE,&tmp); - tmp = self->input_sample_rate; + tmp = this->input_sample_rate; #ifdef FORCE_44K_MAX if(tmp > 44100) tmp = 44100; #endif - if (ioctl(self->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) { + if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) { - printf ("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n", self->input_sample_rate); + printf ("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n", this->input_sample_rate); tmp = 44100; - if (ioctl(self->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) { + if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) { printf ("audio_oss_out: error: 44100 Hz sampling rate not supported\n"); - return -1; + return 0; } } - self->output_sample_rate = tmp; + this->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->input_sample_rate, this->output_sample_rate); } /* * set number of channels / ac3 throughput @@ -202,43 +202,43 @@ static int ao_oss_open(ao_driver_t *self_gen, switch (mode) { case AO_CAP_MODE_MONO: tmp = 1; - ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); - self->num_channels = tmp; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; break; case AO_CAP_MODE_STEREO: tmp = 2; - ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); - self->num_channels = tmp; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; break; case AO_CAP_MODE_4CHANNEL: tmp = 4; - ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); - self->num_channels = tmp; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; break; case AO_CAP_MODE_5CHANNEL: tmp = 5; - ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); - self->num_channels = tmp; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; break; case AO_CAP_MODE_5_1CHANNEL: tmp = 6; - ioctl(self->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); - self->num_channels = tmp; + ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); + this->num_channels = tmp; break; case AO_CAP_MODE_AC3: tmp = AFMT_AC3; - if (ioctl(self->audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 || tmp != AFMT_AC3) { + if (ioctl(this->audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 || tmp != AFMT_AC3) { printf("audio_oss_out: AC3 SNDCTL_DSP_SETFMT failed. %d\n",tmp); - return -1; + return 0; } - self->num_channels = 2; /* FIXME: is this correct ? */ - self->output_sample_rate = self->input_sample_rate; + this->num_channels = 2; /* FIXME: is this correct ? */ + this->output_sample_rate = this->input_sample_rate; printf ("audio_oss_out : AO_CAP_MODE_AC3\n"); break; } - printf ("audio_oss_out : %d channels output\n",self->num_channels); - self->bytes_per_frame=(self->bits_per_sample*self->num_channels)/8; + printf ("audio_oss_out : %d channels output\n",this->num_channels); + this->bytes_per_frame=(this->bits_per_sample*this->num_channels)/8; /* * audio buffer size handling @@ -257,18 +257,18 @@ static int ao_oss_open(ao_driver_t *self_gen, xprintf (VERBOSE|AUDIO, "Audio buffer fragment info : %x\n",tmp); - ioctl(self->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp); + ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp); */ /* * Final check of realtime capability, make sure GETOPTR * doesn't return an error. */ - if ( self->audio_has_realtime && !checked_getoptr ) { + if ( this->audio_has_realtime && !checked_getoptr ) { count_info info; - int ret = ioctl(self->audio_fd, SNDCTL_DSP_GETOPTR, &info); + int ret = ioctl(this->audio_fd, SNDCTL_DSP_GETOPTR, &info); if ( ret == -1 && errno == EINVAL ) { - self->audio_has_realtime = 0; + this->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"); @@ -277,27 +277,42 @@ static int ao_oss_open(ao_driver_t *self_gen, checked_getoptr = 1; } - return 1; + return this->output_sample_rate; } -static int ao_oss_num_channels(ao_driver_t *self_gen) +static int ao_oss_num_channels(ao_driver_t *this_gen) { - oss_driver_t *self = (oss_driver_t *) self_gen; - return self->num_channels; + oss_driver_t *this = (oss_driver_t *) this_gen; + return this->num_channels; } -static int ao_oss_bytes_per_frame(ao_driver_t *self_gen) +static int ao_oss_bytes_per_frame(ao_driver_t *this_gen) { - oss_driver_t *self = (oss_driver_t *) self_gen; - return self->bytes_per_frame; + oss_driver_t *this = (oss_driver_t *) this_gen; + return this->bytes_per_frame; } -static int ao_oss_delay(ao_driver_t *self_gen) +static int ao_oss_delay(ao_driver_t *this_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; + count_info info; + oss_driver_t *this = (oss_driver_t *) this_gen; + int bytes_left; + + if (this->audio_has_realtime) { + ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info); + + /* calc delay */ + + bytes_left = this->bytes_in_buffer - info.bytes; + + if (bytes_left<=0) /* buffer ran dry */ + bytes_left = 0; + } else { + bytes_left = this->static_delay; + } + + + return bytes_left / this->bytes_per_frame; } /* Write audio samples @@ -305,41 +320,43 @@ static int ao_oss_delay(ao_driver_t *self_gen) * 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) +static int ao_oss_write(ao_driver_t *this_gen, + int16_t* frame_buffer, uint32_t num_frames) { - oss_driver_t *self = (oss_driver_t *) self_gen; - return write(self->audio_fd, frame_buffer, num_frames * self->bytes_per_frame); + oss_driver_t *this = (oss_driver_t *) this_gen; + + this->bytes_in_buffer += num_frames * this->bytes_per_frame; + return write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame); } -static void ao_oss_close(ao_driver_t *self_gen) +static void ao_oss_close(ao_driver_t *this_gen) { - oss_driver_t *self = (oss_driver_t *) self_gen; - close(self->audio_fd); - self->audio_fd = -1; + oss_driver_t *this = (oss_driver_t *) this_gen; + close(this->audio_fd); + this->audio_fd = -1; } -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 uint32_t ao_oss_get_capabilities (ao_driver_t *this_gen) { + oss_driver_t *this = (oss_driver_t *) this_gen; + return this->capabilities; } -static void ao_oss_exit(ao_driver_t *self_gen) +static void ao_oss_exit(ao_driver_t *this_gen) { - oss_driver_t *self = (oss_driver_t *) self_gen; + oss_driver_t *this = (oss_driver_t *) this_gen; - if (self->audio_fd != -1) - close(self->audio_fd); + if (this->audio_fd != -1) + close(this->audio_fd); - free (self); + free (this); } /* * */ -static int ao_oss_get_property (ao_driver_t *self_gen, int property) { - oss_driver_t *self = (oss_driver_t *) self; +static int ao_oss_get_property (ao_driver_t *this_gen, int property) { + oss_driver_t *this = (oss_driver_t *) this; /* FIXME: implement some properties switch(property) { @@ -357,8 +374,8 @@ static int ao_oss_get_property (ao_driver_t *self_gen, int property) { /* * */ -static int ao_oss_set_property (ao_driver_t *self_gen, int property, int value) { - oss_driver_t *self = (oss_driver_t *) self; +static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value) { + oss_driver_t *this = (oss_driver_t *) this; /* FIXME: Implement property support. switch(property) { @@ -376,7 +393,7 @@ static int ao_oss_set_property (ao_driver_t *self_gen, int property, int value) ao_driver_t *init_audio_out_plugin (config_values_t *config) { - oss_driver_t *self; + oss_driver_t *this; int caps; #ifdef CONFIG_DEVFS_FS char devname[] = "/dev/sound/dsp\0\0\0"; @@ -389,7 +406,7 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) { int audio_fd; int num_channels, status, arg; - self = (oss_driver_t *) malloc (sizeof (oss_driver_t)); + this = (oss_driver_t *) malloc (sizeof (oss_driver_t)); /* * find best device driver/channel @@ -402,11 +419,11 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) { devnum = config->lookup_int (config, "oss_device_num", -1); if (devnum >= 0) { - sprintf (self->audio_dev, DSP_TEMPLATE, devnum); + sprintf (this->audio_dev, DSP_TEMPLATE, devnum); devnum = 30; /* skip while loop */ } else { devnum = 0; - sprintf (self->audio_dev, "/dev/dsp"); + sprintf (this->audio_dev, "/dev/dsp"); } while (devnum<16) { @@ -420,14 +437,14 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) { rate = 48000; ioctl(audio_fd,SNDCTL_DSP_SPEED, &rate); if (rate>best_rate) { - strncpy (self->audio_dev, devname, 19); + strncpy (this->audio_dev, devname, 19); best_rate = rate; } close (audio_fd); } /*else printf("audio_oss_out: opening audio device %s failed:\n%s\n", - self->audio_dev, strerror(errno)); + this->audio_dev, strerror(errno)); */ sprintf(devname, DSP_TEMPLATE, devnum); @@ -438,18 +455,18 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) { * open that device */ - audio_fd=open(self->audio_dev, O_WRONLY|O_NDELAY); + audio_fd=open(this->audio_dev, O_WRONLY|O_NDELAY); if(audio_fd < 0) { printf("audio_oss_out: opening audio device %s failed:\n%s\n", - self->audio_dev, strerror(errno)); + this->audio_dev, strerror(errno)); - free (self); + free (this); return NULL; } else - xprintf (VERBOSE|AUDIO, " %s\n", self->audio_dev); + xprintf (VERBOSE|AUDIO, " %s\n", this->audio_dev); /* * set up driver to reasonable values for capabilities tests @@ -468,38 +485,38 @@ ao_driver_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"); - self->audio_has_realtime = 1; + this->audio_has_realtime = 1; } else { printf ("audio_oss_out : realtime check: *FAILED* :-(((((\n"); - self->audio_has_realtime = 0; + this->audio_has_realtime = 0; } - if( !self->audio_has_realtime ) { + if( !this->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"); } - self->capabilities = 0; + this->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) ) { - self->capabilities |= AO_CAP_MODE_MONO; + this->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) ) { - self->capabilities |= AO_CAP_MODE_STEREO; + this->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)) { - self->capabilities |= AO_CAP_MODE_4CHANNEL; + this->capabilities |= AO_CAP_MODE_4CHANNEL; printf ("4-channel "); } else printf ("(4-channel not enabled in .xinerc) " ); @@ -508,7 +525,7 @@ ao_driver_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)) { - self->capabilities |= AO_CAP_MODE_5CHANNEL; + this->capabilities |= AO_CAP_MODE_5CHANNEL; printf ("5-channel "); } else printf ("(5-channel not enabled in .xinerc) " ); @@ -517,7 +534,7 @@ ao_driver_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)) { - self->capabilities |= AO_CAP_MODE_5_1CHANNEL; + this->capabilities |= AO_CAP_MODE_5_1CHANNEL; printf ("5.1-channel "); } else printf ("(5.1-channel not enabled in .xinerc) " ); @@ -526,7 +543,7 @@ ao_driver_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)) { - self->capabilities |= AO_CAP_MODE_AC3; + this->capabilities |= AO_CAP_MODE_AC3; printf ("ac3-pass-through "); } else printf ("(ac3-pass-through not enabled in .xinerc)"); @@ -536,21 +553,23 @@ ao_driver_t *init_audio_out_plugin (config_values_t *config) { close (audio_fd); - 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; + this->output_sample_rate = 0; + this->audio_fd = -1; + + this->static_delay = config->lookup_int (config, "oss_static_delay", 1000); + + this->ao_driver.get_capabilities = ao_oss_get_capabilities; + this->ao_driver.get_property = ao_oss_get_property; + this->ao_driver.set_property = ao_oss_set_property; + this->ao_driver.open = ao_oss_open; + this->ao_driver.num_channels = ao_oss_num_channels; + this->ao_driver.bytes_per_frame = ao_oss_bytes_per_frame; + this->ao_driver.delay = ao_oss_delay; + this->ao_driver.write = ao_oss_write; + this->ao_driver.close = ao_oss_close; + this->ao_driver.exit = ao_oss_exit; + + return &this->ao_driver; } static ao_info_t ao_info_oss = { diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 462890ffc..1547ea8a7 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -17,7 +17,7 @@ * 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.6 2001/08/22 16:20:13 guenter Exp $ + * $Id: audio_out.c,v 1.7 2001/08/23 21:40:05 guenter Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> @@ -66,118 +66,128 @@ #include "metronom.h" #include "utils.h" -/* bufsize must be a multiple of 3 and 5 for 5.0 and 5.1 channel playback! */ -#define ZERO_BUF_SIZE 15360 +#define ZERO_BUF_SIZE 5000 #define GAP_TOLERANCE 5000 #define MAX_GAP 90000 struct frmsize_s { - uint16_t bit_rate; - uint16_t frm_size[3]; + uint16_t bit_rate; + uint16_t frm_size[3]; }; static const struct frmsize_s frmsizecod_tbl[64] = { - { 32 ,{64 ,69 ,96 } }, - { 32 ,{64 ,70 ,96 } }, - { 40 ,{80 ,87 ,120 } }, - { 40 ,{80 ,88 ,120 } }, - { 48 ,{96 ,104 ,144 } }, - { 48 ,{96 ,105 ,144 } }, - { 56 ,{112 ,121 ,168 } }, - { 56 ,{112 ,122 ,168 } }, - { 64 ,{128 ,139 ,192 } }, - { 64 ,{128 ,140 ,192 } }, - { 80 ,{160 ,174 ,240 } }, - { 80 ,{160 ,175 ,240 } }, - { 96 ,{192 ,208 ,288 } }, - { 96 ,{192 ,209 ,288 } }, - { 112 ,{224 ,243 ,336 } }, - { 112 ,{224 ,244 ,336 } }, - { 128 ,{256 ,278 ,384 } }, - { 128 ,{256 ,279 ,384 } }, - { 160 ,{320 ,348 ,480 } }, - { 160 ,{320 ,349 ,480 } }, - { 192 ,{384 ,417 ,576 } }, - { 192 ,{384 ,418 ,576 } }, - { 224 ,{448 ,487 ,672 } }, - { 224 ,{448 ,488 ,672 } }, - { 256 ,{512 ,557 ,768 } }, - { 256 ,{512 ,558 ,768 } }, - { 320 ,{640 ,696 ,960 } }, - { 320 ,{640 ,697 ,960 } }, - { 384 ,{768 ,835 ,1152 } }, - { 384 ,{768 ,836 ,1152 } }, - { 448 ,{896 ,975 ,1344 } }, - { 448 ,{896 ,976 ,1344 } }, - { 512 ,{1024 ,1114 ,1536 } }, - { 512 ,{1024 ,1115 ,1536 } }, - { 576 ,{1152 ,1253 ,1728 } }, - { 576 ,{1152 ,1254 ,1728 } }, - { 640 ,{1280 ,1393 ,1920 } }, - { 640 ,{1280 ,1394 ,1920 } } + { 32 ,{64 ,69 ,96 } }, + { 32 ,{64 ,70 ,96 } }, + { 40 ,{80 ,87 ,120 } }, + { 40 ,{80 ,88 ,120 } }, + { 48 ,{96 ,104 ,144 } }, + { 48 ,{96 ,105 ,144 } }, + { 56 ,{112 ,121 ,168 } }, + { 56 ,{112 ,122 ,168 } }, + { 64 ,{128 ,139 ,192 } }, + { 64 ,{128 ,140 ,192 } }, + { 80 ,{160 ,174 ,240 } }, + { 80 ,{160 ,175 ,240 } }, + { 96 ,{192 ,208 ,288 } }, + { 96 ,{192 ,209 ,288 } }, + { 112 ,{224 ,243 ,336 } }, + { 112 ,{224 ,244 ,336 } }, + { 128 ,{256 ,278 ,384 } }, + { 128 ,{256 ,279 ,384 } }, + { 160 ,{320 ,348 ,480 } }, + { 160 ,{320 ,349 ,480 } }, + { 192 ,{384 ,417 ,576 } }, + { 192 ,{384 ,418 ,576 } }, + { 224 ,{448 ,487 ,672 } }, + { 224 ,{448 ,488 ,672 } }, + { 256 ,{512 ,557 ,768 } }, + { 256 ,{512 ,558 ,768 } }, + { 320 ,{640 ,696 ,960 } }, + { 320 ,{640 ,697 ,960 } }, + { 384 ,{768 ,835 ,1152 } }, + { 384 ,{768 ,836 ,1152 } }, + { 448 ,{896 ,975 ,1344 } }, + { 448 ,{896 ,976 ,1344 } }, + { 512 ,{1024 ,1114 ,1536 } }, + { 512 ,{1024 ,1115 ,1536 } }, + { 576 ,{1152 ,1253 ,1728 } }, + { 576 ,{1152 ,1254 ,1728 } }, + { 640 ,{1280 ,1393 ,1920 } }, + { 640 ,{1280 ,1394 ,1920 } } }; /* * open the audio device for writing to */ -static int ao_open(ao_instance_t *self, +static int ao_open(ao_instance_t *this, 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"); + int output_sample_rate; + if ((output_sample_rate=this->driver->open(this->driver,bits,rate,mode)) == 0) { + printf("audio_out: open failed!\n"); return -1; }; - self->mode = mode; - self->input_frame_rate = rate; - self->frames_in_buffer = 0; - self->audio_started = 0; - self->last_audio_vpts = 0; - self->do_resample = 0; /* Resampling currently not working. */ + printf("audio_out: output sample rate %d\n", output_sample_rate); - self->output_frame_rate=rate; - self->num_channels = self->driver->num_channels(self->driver); + this->mode = mode; + this->input_frame_rate = rate; + this->audio_started = 0; + this->last_audio_vpts = 0; - self->frame_rate_factor = (double) self->output_frame_rate / (double) self->input_frame_rate; /* always produces 1 at the moment */ - self->audio_step = (uint32_t) 90000 * (uint32_t) 32768 - / self->input_frame_rate; - self->frames_per_kpts = self->output_frame_rate * self->num_channels * 2 * 1024 / 90000; - xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 frames\n", self->audio_step); + this->output_frame_rate = output_sample_rate; - self->metronom->set_audio_rate(self->metronom, self->audio_step); + 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_frame_rate != this->input_frame_rate; + } + if (this->do_resample) + printf("audio_out: will resample audio from %d to %d\n", + this->input_frame_rate, this->output_frame_rate); + + this->num_channels = this->driver->num_channels(this->driver); + this->frame_rate_factor = (double) this->output_frame_rate / (double) this->input_frame_rate; + this->audio_step = (uint32_t) 90000 * (uint32_t) 32768 / this->input_frame_rate; + this->frames_per_kpts = this->output_frame_rate * 1024 / 90000; + xprintf (VERBOSE|AUDIO, "audio_out : audio_step %d pts per 32768 frames\n", this->audio_step); + + this->metronom->set_audio_rate(this->metronom, this->audio_step); return 1; } -static void ao_fill_gap (ao_instance_t *self, uint32_t pts_len) { +static void ao_fill_gap (ao_instance_t *this, uint32_t pts_len) { - int num_bytes ; + int num_frames ; 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 */ + num_frames = pts_len * this->frames_per_kpts / 1024; - printf ("audio_out: inserting %d 0-bytes to fill a gap of %d pts\n",num_bytes, pts_len); + if (this->mode == AO_CAP_MODE_AC3) return; /* FIXME */ - self->frames_in_buffer += num_bytes; + printf ("audio_out: inserting %d 0-frames to fill a gap of %d pts\n",num_frames, pts_len); - 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; + while (num_frames > 0) { + if (num_frames > ZERO_BUF_SIZE) { + this->driver->write(this->driver, this->zero_space, ZERO_BUF_SIZE); + num_frames -= ZERO_BUF_SIZE; } else { - self->driver->write(self->driver, self->zero_space, num_bytes); - num_bytes = 0; + this->driver->write(this->driver, this->zero_space, num_frames); + num_frames = 0; } } } @@ -189,7 +199,7 @@ static void ao_fill_gap (ao_instance_t *self, uint32_t pts_len) { * So it has moved to here. */ -void write_pause_burst(ao_instance_t *self, int error) +void write_pause_burst(ao_instance_t *this, int error) { unsigned char buf[8192]; unsigned short *sbuf = (unsigned short *)&buf[0]; @@ -209,139 +219,134 @@ void write_pause_burst(ao_instance_t *self, int error) sbuf[5] = 0x0000; memset(&sbuf[6], 0, 6144 - 96); - self->driver->write(self->driver, sbuf, 6144 / 4); + this->driver->write(this->driver, sbuf, 6144 / 4); } -static int ao_write(ao_instance_t *self, +static int ao_write(ao_instance_t *this, int16_t* output_frames, uint32_t num_frames, - uint32_t pts_) + uint32_t pts) { - uint32_t vpts, buffer_vpts; - int32_t gap; - int bDropPackage; - int pos; - int frame_size; - int fscod; - int frmsizecod; - uint8_t *data; + uint32_t vpts, buffer_vpts; + int32_t gap; + int bDropPackage; + int delay; + int frame_size; + int fscod; + int frmsizecod; + uint8_t *data; - if (self->driver<0) + if (this->driver<0) return 1; - vpts = self->metronom->got_audio_samples (self->metronom, pts_, num_frames); + vpts = this->metronom->got_audio_samples (this->metronom, pts, num_frames); xprintf (VERBOSE|AUDIO, "audio_out: got %d frames, vpts=%d pts=%d\n", - num_frames, vpts,pts_); + 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) + if (vpts<this->last_audio_vpts) { + /* reject this */ + xprintf (VERBOSE|AUDIO, "audio_out: rejected frame vpts=%d, last_audio_vpts=%d\n", vpts,this->last_audio_vpts) return 1; } - self->last_audio_vpts = vpts; + this->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; + /* + * where, in the timeline is the "end" of the audio buffer at the moment? + */ + + buffer_vpts = this->metronom->get_current_time (this->metronom); - /* - * calculate gap: - */ + if (this->audio_started) + delay = this->driver->delay(this->driver); + else + delay = 0; + + /* External AC3 decoder delay correction */ + if (this->mode==AO_CAP_MODE_AC3) + delay+=10; + + buffer_vpts += delay * 1024 / this->frames_per_kpts; - 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); + /* + * calculate gap: + */ + + gap = vpts - buffer_vpts; + + if (gap>GAP_TOLERANCE) { + ao_fill_gap (this, gap); - if (gap>GAP_TOLERANCE) { - ao_fill_gap (self, gap); - - /* keep xine responsive */ + /* keep xine responsive */ - if (gap>MAX_GAP) - return 0; + 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); - } + } 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 (this->mode == AO_CAP_MODE_AC3) + bDropPackage=0; if (!bDropPackage) { - int num_output_frames = num_frames * (self->output_frame_rate) / self->input_frame_rate; + int num_output_frames = (double) num_frames * this->frame_rate_factor; - if ((!self->do_resample) && (self->mode != AO_CAP_MODE_AC3)) { + if ((!this->do_resample) && (this->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) { + this->driver->write (this->driver, output_frames, + num_output_frames ); + } else switch (this->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); + this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->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); + this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->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); + this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->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); + this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->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); + this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->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 */ + this->frame_buffer[0] = 0xf872; /* spdif syncword */ + this->frame_buffer[1] = 0x4e1f; /* ............. */ + this->frame_buffer[2] = 0x0001; /* AC3 data */ data = (uint8_t *)&output_frames[1]; /* skip AC3 sync */ fscod = (data[2] >> 6) & 0x3; frmsizecod = data[2] & 0x3f; frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] << 4; - self->frame_buffer[3] = frame_size; + this->frame_buffer[3] = frame_size; /* 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); + swab(output_frames,this->frame_buffer+4, num_frames ); + this->driver->write(this->driver, this->zero_space, 2); /* Prevents crackle at start. */ + this->driver->write(this->driver, this->frame_buffer, num_output_frames); + this->driver->write(this->driver, this->zero_space, 1534-num_output_frames); num_output_frames=num_output_frames; break; } @@ -352,8 +357,7 @@ static int ao_write(ao_instance_t *self, * step values */ - self->frames_in_buffer += num_output_frames ; - self->audio_started = 1; + this->audio_started = 1; } return 1; @@ -361,34 +365,37 @@ static int ao_write(ao_instance_t *self, } -static void ao_close(ao_instance_t *self) +static void ao_close(ao_instance_t *this) { - self->driver->close(self->driver); + this->driver->close(this->driver); } -static uint32_t ao_get_capabilities (ao_instance_t *self) { +static uint32_t ao_get_capabilities (ao_instance_t *this) { uint32_t result; - result=self->driver->get_capabilities(self->driver); + result=this->driver->get_capabilities(this->driver); return result; } -ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom) { +ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom, + config_values_t *config) { + + ao_instance_t *this; - ao_instance_t *self; + this = xmalloc (sizeof (ao_instance_t)) ; - self = xmalloc (sizeof (ao_instance_t)) ; + this->driver = driver; + this->metronom = metronom; - self->driver = driver; - self->metronom = metronom; + this->open = ao_open; + this->write = ao_write; + this->close = ao_close; + this->get_capabilities = ao_get_capabilities; + this->audio_loop_running = 0; + this->frame_buffer = xmalloc (40000); + this->zero_space = xmalloc (ZERO_BUF_SIZE * 2 * 6); - 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 = xmalloc (40000); - self->zero_space = xmalloc (ZERO_BUF_SIZE); + this->resample_conf = config->lookup_int (config, "audio_resample_mode", 0); - return self; + return this; } diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index 27b4c2f2d..c7ea69b3e 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.9 2001/08/21 19:39:50 jcdutton Exp $ + * $Id: audio_out.h,v 1.10 2001/08/23 21:40:05 guenter Exp $ */ #ifndef HAVE_AUDIO_OUT_H #define HAVE_AUDIO_OUT_H @@ -58,7 +58,7 @@ struct ao_driver_s { * open the driver and make it ready to receive audio data * buffers may be flushed(!) * - * return value: <=0 : failure, 1 : ok + * return value: 0 : failure, >0 : output sample rate */ int (*open)(ao_driver_t *this, uint32_t bits, uint32_t rate, int mode); @@ -123,7 +123,7 @@ struct ao_instance_s { /* open display driver for video output */ int (*open) (ao_instance_t *this, - uint32_t bits, uint32_t rate, int mode); + uint32_t bits, uint32_t rate, int mode); /* * write audio data to output buffer @@ -135,8 +135,8 @@ struct ao_instance_s { */ int (*write)(ao_driver_t *this, - int16_t* audio_data, uint32_t num_frames, - uint32_t pts); + 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); @@ -146,37 +146,30 @@ struct ao_instance_s { /* 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; + 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; /* frames per 1024/90000 sec */ + int32_t output_frame_rate, input_frame_rate; + double frame_rate_factor; + uint32_t num_channels; + int audio_started; + uint32_t last_audio_vpts; + int resample_conf; + int do_resample; + int mode; + uint16_t *frame_buffer; + int16_t *zero_space; }; /* 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) ; +ao_instance_t *ao_new_instance (ao_driver_t *driver, metronom_t *metronom, config_values_t *config) ; /* * to build a dynamic audio output plugin, * you have to implement these driver: diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 17fd9385b..4d4033934 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.45 2001/08/21 19:39:50 jcdutton Exp $ + * $Id: xine.c,v 1.46 2001/08/23 21:40:05 guenter Exp $ * * top-level xine functions * @@ -515,7 +515,7 @@ xine_t *xine_init (vo_driver_t *vo, video_decoder_init (this); if(ao) { - this->audio_out = ao_new_instance (ao, this->metronom); + this->audio_out = ao_new_instance (ao, this->metronom, config); // this->audio_out = ao; // this->audio_out->connect (this->audio_out, this->metronom); } diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 8c91426e6..39ede9b61 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.39 2001/08/21 19:39:50 jcdutton Exp $ + * $Id: xine_internal.h,v 1.40 2001/08/23 21:40:05 guenter Exp $ * */ @@ -167,7 +167,7 @@ struct xine_s { video_decoder_t *cur_video_decoder_plugin; int video_finished; - ao_instance_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]; |