diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-03-26 01:47:17 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-03-26 01:47:17 +0000 |
commit | c97b86045b81f7ee758acb7f835bbd2a697c03d0 (patch) | |
tree | ad792557788a992d5ba2534f54671ce4bc072df3 | |
parent | 76927755fa6782d3df74ecd9d95a92bf429fad5f (diff) | |
download | xine-lib-c97b86045b81f7ee758acb7f835bbd2a697c03d0.tar.gz xine-lib-c97b86045b81f7ee758acb7f835bbd2a697c03d0.tar.bz2 |
sound card clock drift patch
CVS patchset: 1635
CVS date: 2002/03/26 01:47:17
-rw-r--r-- | src/xine-engine/audio_out.c | 67 | ||||
-rw-r--r-- | src/xine-engine/audio_out.h | 4 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 12 | ||||
-rw-r--r-- | src/xine-engine/metronom.h | 7 |
4 files changed, 69 insertions, 21 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 27dc57dfb..52e568339 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.48 2002/03/19 02:12:49 guenter Exp $ + * $Id: audio_out.c,v 1.49 2002/03/26 01:47:17 miguelfreitas Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> @@ -76,6 +76,32 @@ #define ZERO_BUF_SIZE 5000 +/* By adding gap errors (difference between reported and expected + * sound card clock) into metronom's vpts_offset we can use its + * smoothing algorithms to correct sound card clock drifts. + * obs: previously this error was added to xine scr. + * + * audio buf ---> metronom --> audio fifo --> (buf->vpts - hw_vpts) + * (vpts_offset + error) gap + * <---------- control --------------| + * + * Unfortunately audio fifo adds a large delay to our closed loop. + * + * These are designed to avoid updating the metronom too fast. + * - it will only be updated 1 time per second (so it has a chance of + * distributing the error for several frames). + * - it will only be updated 2 times for the whole audio fifo size + * length (so the control will wait to see the feedback effect) + * - each update will be of gap/SYNC_GAP_RATE. + * + * Sound card clock correction can only provide smooth playback for + * errors < 1% nominal rate. For bigger errors (bad streams) audio + * buffers may be dropped or gaps filled with silence. + */ +#define SYNC_TIME_INVERVAL (1 * 90000) +#define SYNC_BUF_INTERVAL NUM_AUDIO_BUFFERS / 2 +#define SYNC_GAP_RATE 4 + struct audio_fifo_s { audio_buffer_t *first; audio_buffer_t *last; @@ -240,12 +266,16 @@ static void *ao_loop (void *this_gen) { int64_t cur_time; int num_output_frames ; int paused_wait; + int64_t last_sync_time; + int bufs_since_sync; - + last_sync_time = bufs_since_sync = 0; + while ((this->audio_loop_running) || (!this->audio_loop_running && this->out_fifo->first)) { buf = fifo_remove (this->out_fifo); + bufs_since_sync++; do { delay = this->driver->delay(this->driver); @@ -294,8 +324,8 @@ static void *ao_loop (void *this_gen) { /* * output audio data synced to master clock */ - - if (gap < (-1 * this->gap_tolerance) || !buf->num_frames || + + if (gap < (-1 * AO_MAX_GAP) || !buf->num_frames || this->audio_paused ) { /* drop package */ @@ -306,19 +336,24 @@ static void *ao_loop (void *this_gen) { #endif } else { - - if (gap>this->gap_tolerance) { - - if (gap>15000) - ao_fill_gap (this, gap); - else { - printf ("audio_out: adjusting master clock %lld -> %lld\n", - cur_time, cur_time + gap); - this->metronom->adjust_clock (this->metronom, - cur_time + gap); - } - } + /* for small gaps ( tolerance < abs(gap) < AO_MAX_GAP ) + * feedback them into metronom's vpts_offset. + */ + if ( abs(gap) < AO_MAX_GAP && abs(gap) > this->gap_tolerance && + cur_time > (last_sync_time + SYNC_TIME_INVERVAL) && + bufs_since_sync >= SYNC_BUF_INTERVAL ) { + + this->metronom->set_option(this->metronom, METRONOM_ADJ_VPTS_OFFSET, + -gap/SYNC_GAP_RATE ); + last_sync_time = cur_time; + bufs_since_sync = 0; + } + + /* for big gaps output silence */ + if ( gap > AO_MAX_GAP ) { + ao_fill_gap (this, gap/2); + } /* * resample and output audio data diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index 03600edcf..fb73dc483 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.27 2002/03/19 02:12:50 guenter Exp $ + * $Id: audio_out.h,v 1.28 2002/03/26 01:47:17 miguelfreitas Exp $ */ #ifndef HAVE_AUDIO_OUT_H #define HAVE_AUDIO_OUT_H @@ -273,6 +273,8 @@ ao_instance_t *ao_new_instance (ao_driver_t *driver, xine_t *xine) ; #define AO_CTRL_PLAY_RESUME 1 #define AO_CTRL_FLUSH_BUFFERS 2 +/* above that value audio frames are discarded */ +#define AO_MAX_GAP 15000 typedef struct ao_info_s { diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 5846e5408..689274239 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.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: metronom.c,v 1.75 2002/03/24 14:15:37 guenter Exp $ + * $Id: metronom.c,v 1.76 2002/03/26 01:47:17 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -471,7 +471,9 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, else { if( this->audio_samples ) { /* calculate drift_step to recover vpts errors */ +#ifdef LOG printf("audio diff = %lld ", diff ); +#endif diff *= AUDIO_SAMPLE_NUM; diff /= this->audio_samples * 4; @@ -483,8 +485,10 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, this->audio_drift_step = diff; +#ifdef LOG printf("audio_drift = %lld, pts_per_smpls = %lld\n", diff, this->pts_per_smpls ); +#endif } } this->audio_samples = 0; @@ -516,6 +520,12 @@ static void metronom_set_option (metronom_t *this, int option, int64_t value) { case METRONOM_SCR_ADJUSTABLE: this->scr_adjustable = value; break; + case METRONOM_ADJ_VPTS_OFFSET: + this->vpts_offset += value; +/*#ifdef LOG*/ + printf ("metronom: adjusting vpts_offset by %lld\n", value ); +/*#endif*/ + break; default: printf ("metronom: unknown option in set_option: %d\n", option); diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 4f7d9ebb7..b49303a63 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.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: metronom.h,v 1.25 2002/03/23 18:56:56 guenter Exp $ + * $Id: metronom.h,v 1.26 2002/03/26 01:47:17 miguelfreitas Exp $ * * metronom: general pts => virtual calculation/assoc * @@ -244,8 +244,9 @@ metronom_t *metronom_init (int have_audio, void *xine); * metronom options */ -#define METRONOM_SCR_ADJUSTABLE 1 -#define METRONOM_AV_OFFSET 2 +#define METRONOM_SCR_ADJUSTABLE 1 +#define METRONOM_AV_OFFSET 2 +#define METRONOM_ADJ_VPTS_OFFSET 3 /* * SCR (system clock reference) plugins |