diff options
Diffstat (limited to 'src/xine-engine/audio_out.c')
-rw-r--r-- | src/xine-engine/audio_out.c | 105 |
1 files changed, 73 insertions, 32 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 0c7310557..a17f438c8 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.74 2002/10/24 17:51:30 guenter Exp $ + * $Id: audio_out.c,v 1.75 2002/10/29 16:02:45 mroi Exp $ * * 22-8-2001 James imported some useful AC3 sections from the previous alsa driver. * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> @@ -136,11 +136,9 @@ static audio_fifo_t *fifo_new () { return fifo; } -static void fifo_append (audio_fifo_t *fifo, +static void fifo_append_int (audio_fifo_t *fifo, audio_buffer_t *buf) { - pthread_mutex_lock (&fifo->mutex); - buf->next = NULL; if (!fifo->first) { @@ -156,16 +154,19 @@ static void fifo_append (audio_fifo_t *fifo, fifo->num_buffers++; } - pthread_cond_signal (&fifo->not_empty); - pthread_mutex_unlock (&fifo->mutex); } -static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) { - - audio_buffer_t *buf; +static void fifo_append (audio_fifo_t *fifo, + audio_buffer_t *buf) { pthread_mutex_lock (&fifo->mutex); + fifo_append_int (fifo, buf); + pthread_mutex_unlock (&fifo->mutex); +} + +static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo) { + audio_buffer_t *buf; while (!fifo->first) { pthread_cond_wait (&fifo->not_empty, &fifo->mutex); @@ -187,11 +188,21 @@ static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) { } + return buf; +} + +static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) { + + audio_buffer_t *buf; + + pthread_mutex_lock (&fifo->mutex); + buf = fifo_remove_int(fifo); pthread_mutex_unlock (&fifo->mutex); return buf; } + void write_pause_burst(ao_instance_t *this, uint32_t num_frames) { int error = 0; @@ -320,7 +331,7 @@ static void audio_filter_compress (ao_instance_t *this, int16_t *mem, int num_fr this->compression_factor = this->compression_factor_max; } -#if LOG +#ifdef LOG printf ("audio_out: max=%d f_max=%f compression_factor=%f\n", maxs, f_max, this->compression_factor); #endif @@ -471,11 +482,8 @@ static void *ao_loop (void *this_gen) { int64_t gap; int64_t delay; int64_t cur_time; - /* int num_output_frames ;*/ - /* int paused_wait; */ int64_t last_sync_time; int bufs_since_sync; - /* double acc_output_frames, output_frame_excess = 0; */ last_sync_time = bufs_since_sync = 0; #ifdef LOG @@ -490,12 +498,21 @@ static void *ao_loop (void *this_gen) { while ((this->audio_loop_running) || (!this->audio_loop_running && this->out_fifo->first)) { + + if (this->flush_audio_driver) { +#ifdef LOG + printf ("audio_out: flush audio driver\n"); +#endif + this->control(this, AO_CTRL_FLUSH_BUFFERS); + this->flush_audio_driver = 0; + } + /* wait until user unpauses stream audio_paused == 1 means we are playing at a different speed them we must process buffers otherwise the entire engine will stop. */ - while ( this->audio_paused ) { + while ( this->audio_paused && this->audio_loop_running ) { switch (this->audio_paused) { case 1: { @@ -512,7 +529,7 @@ static void *ao_loop (void *this_gen) { } case 2: { - this->metronom->allow_full_ao_fill_gap = 1; + this->allow_full_ao_fill_gap = 1; #ifdef LOG printf ("audio_out:loop:pause: I feel sleepy.\n"); #endif @@ -526,7 +543,7 @@ static void *ao_loop (void *this_gen) { } /* pthread_mutex_lock( &this->driver_lock ); What is this lock for ? */ delay = this->driver->delay(this->driver); - while (delay <=0) { + while (delay <=0 && this->audio_loop_running) { /* Get the audio card into RUNNING state. */ ao_fill_gap (this, 10000); /* FIXME, this PTS of 1000 should == period size */ delay = this->driver->delay(this->driver); @@ -586,8 +603,9 @@ static void *ao_loop (void *this_gen) { } else 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 ) { - +#ifdef LOG printf ("audio_out: audio_loop: ADJ_VPTS\n"); +#endif this->metronom->set_option(this->metronom, METRONOM_ADJ_VPTS_OFFSET, -gap/SYNC_GAP_RATE ); last_sync_time = cur_time; @@ -595,9 +613,9 @@ static void *ao_loop (void *this_gen) { } else if ( gap > AO_MAX_GAP ) { /* for big gaps output silence */ - if (this->metronom->allow_full_ao_fill_gap) { + if (this->allow_full_ao_fill_gap) { ao_fill_gap (this, gap); - this->metronom->allow_full_ao_fill_gap = 0; + this->allow_full_ao_fill_gap = 0; } else { ao_fill_gap (this, gap / 2); } @@ -955,6 +973,26 @@ static int ao_control (ao_instance_t *this, int cmd, ...) { return rval; } +static void ao_flush (ao_instance_t *this) { + audio_buffer_t *buf; + int i, num_buffers; + + pthread_mutex_lock (&this->out_fifo->mutex); + pthread_mutex_lock (&this->free_fifo->mutex); + num_buffers = this->out_fifo->num_buffers; + printf ("audio_out: flush fifo (%d buffers)\n", num_buffers); + + for (i = 0; i < this->out_fifo->num_buffers; i++) { + buf = fifo_remove_int (this->out_fifo); + fifo_append_int (this->free_fifo, buf); + } + + this->flush_audio_driver = 1; + this->allow_full_ao_fill_gap = 1; + pthread_mutex_unlock (&this->free_fifo->mutex); + pthread_mutex_unlock (&this->out_fifo->mutex); +} + ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, xine_stream_t *stream) { @@ -971,19 +1009,22 @@ ao_instance_t *ao_new_instance (xine_ao_driver_t *driver, this->stream = stream; pthread_mutex_init( &this->driver_lock, NULL ); - this->open = ao_open; - this->get_buffer = ao_get_buffer; - this->put_buffer = ao_put_buffer; - this->close = ao_close; - this->exit = ao_exit; - this->get_capabilities = ao_get_capabilities; - this->get_property = ao_get_property; - this->set_property = ao_set_property; - this->control = ao_control; - this->audio_loop_running = 0; - this->audio_paused = 0; - this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 2 * 6); - this->gap_tolerance = driver->get_gap_tolerance (this->driver); + this->open = ao_open; + this->get_buffer = ao_get_buffer; + this->put_buffer = ao_put_buffer; + this->close = ao_close; + this->exit = ao_exit; + this->get_capabilities = ao_get_capabilities; + this->get_property = ao_get_property; + this->set_property = ao_set_property; + this->control = ao_control; + this->flush = ao_flush; + this->audio_loop_running = 0; + this->audio_paused = 0; + this->flush_audio_driver = 0; + this->allow_full_ao_fill_gap = 0; + this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 2 * 6); + this->gap_tolerance = driver->get_gap_tolerance (this->driver); this->resample_conf = config->register_enum (config, "audio.resample_mode", 0, resample_modes, |