summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2002-11-12 00:15:08 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2002-11-12 00:15:08 +0000
commit637109df37e8e75e2d1947710f82c62f28b465ac (patch)
treefbfb52526696779522751792eb87262b80ba6b08
parentc5dd03adfe9290487c8b041909166ed7c7ed16ff (diff)
downloadxine-lib-637109df37e8e75e2d1947710f82c62f28b465ac.tar.gz
xine-lib-637109df37e8e75e2d1947710f82c62f28b465ac.tar.bz2
fix buffer leakage in ao_loop, re-introduce lock around all driver functions, try to avoid deadlocks when exiting ao_loop, clean up code
CVS patchset: 3245 CVS date: 2002/11/12 00:15:08
-rw-r--r--src/xine-engine/audio_out.c137
1 files changed, 84 insertions, 53 deletions
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 4f07c6ad5..5eca9579a 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.78 2002/11/11 23:41:25 tmattern Exp $
+ * $Id: audio_out.c,v 1.79 2002/11/12 00:15:08 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>
@@ -137,7 +137,7 @@ static audio_fifo_t *fifo_new () {
}
static void fifo_append_int (audio_fifo_t *fifo,
- audio_buffer_t *buf) {
+ audio_buffer_t *buf) {
buf->next = NULL;
@@ -160,6 +160,8 @@ static void fifo_append_int (audio_fifo_t *fifo,
static void fifo_append (audio_fifo_t *fifo,
audio_buffer_t *buf) {
+ assert (!buf->next);
+
pthread_mutex_lock (&fifo->mutex);
fifo_append_int (fifo, buf);
pthread_mutex_unlock (&fifo->mutex);
@@ -187,6 +189,8 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo) {
fifo->num_buffers--;
}
+
+ buf->next = NULL;
return buf;
}
@@ -203,8 +207,8 @@ static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) {
}
-void write_pause_burst(ao_instance_t *this, uint32_t num_frames)
-{
+void write_pause_burst(ao_instance_t *this, uint32_t num_frames) {
+
int error = 0;
unsigned char buf[8192];
unsigned short *sbuf = (unsigned short *)&buf[0];
@@ -226,10 +230,14 @@ void write_pause_burst(ao_instance_t *this, uint32_t num_frames)
memset(&sbuf[6], 0, 6144 - 96);
while (num_frames > 1536) {
if(num_frames > 1536) {
+ pthread_mutex_lock( &this->driver_lock );
this->driver->write(this->driver, sbuf, 1536);
+ pthread_mutex_unlock( &this->driver_lock );
num_frames -= 1536;
} else {
+ pthread_mutex_lock( &this->driver_lock );
this->driver->write(this->driver, sbuf, num_frames);
+ pthread_mutex_unlock( &this->driver_lock );
num_frames = 0;
}
}
@@ -253,10 +261,14 @@ static void ao_fill_gap (ao_instance_t *this, int64_t pts_len) {
while (num_frames > 0) {
if (num_frames > ZERO_BUF_SIZE) {
+ pthread_mutex_lock( &this->driver_lock );
this->driver->write(this->driver, this->zero_space, ZERO_BUF_SIZE);
+ pthread_mutex_unlock( &this->driver_lock );
num_frames -= ZERO_BUF_SIZE;
} else {
+ pthread_mutex_lock( &this->driver_lock );
this->driver->write(this->driver, this->zero_space, num_frames);
+ pthread_mutex_unlock( &this->driver_lock );
num_frames = 0;
}
}
@@ -478,7 +490,7 @@ static void *ao_loop (void *this_gen) {
ao_instance_t *this = (ao_instance_t *) this_gen;
int64_t hw_vpts;
- audio_buffer_t *buf, *in_buf, *out_buf;
+ audio_buffer_t *in_buf, *out_buf;
int64_t gap;
int64_t delay;
int64_t cur_time;
@@ -486,17 +498,26 @@ static void *ao_loop (void *this_gen) {
int bufs_since_sync;
last_sync_time = bufs_since_sync = 0;
+ in_buf = NULL;
+
+ while ((this->audio_loop_running) ||
+ (!this->audio_loop_running && this->out_fifo->first)) {
+
+ /*
+ * get buffer to process for this loop iteration
+ */
+
+ if (!in_buf) {
+
#ifdef LOG
- printf ("audio_out:loop: next fifo\n");
+ printf ("audio_out:loop: get buf from fifo\n");
#endif
- in_buf = buf = fifo_remove (this->out_fifo);
- bufs_since_sync++;
+ in_buf = fifo_remove (this->out_fifo);
+ bufs_since_sync++;
#ifdef LOG
- printf ("audio_out: got a buffer\n");
+ printf ("audio_out: got a buffer\n");
#endif
-
- while ((this->audio_loop_running) ||
- (!this->audio_loop_running && this->out_fifo->first)) {
+ }
if (this->flush_audio_driver) {
#ifdef LOG
@@ -506,48 +527,47 @@ static void *ao_loop (void *this_gen) {
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.
- */
+ /*
+ * 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 && this->audio_loop_running ) {
- switch (this->audio_paused) {
- case 1:
- {
- cur_time = this->metronom->get_current_time (this->metronom);
- if (buf->vpts < cur_time ) {
+ if ( this->audio_paused && this->audio_loop_running ) {
+
+ if (this->audio_paused == 1) {
+
+ cur_time = this->metronom->get_current_time (this->metronom);
+ if (in_buf->vpts < cur_time ) {
#ifdef LOG
- printf ("audio_out:loop: next fifo\n");
+ printf ("audio_out:loop: next fifo\n");
#endif
- fifo_append (this->free_fifo, in_buf);
- in_buf = buf = fifo_remove (this->out_fifo);
- bufs_since_sync++;
- }
- /* We want it to fall through to case 2: */
- }
- case 2:
- {
- this->allow_full_ao_fill_gap = 1;
+ fifo_append (this->free_fifo, in_buf);
+ in_buf = NULL;
+ }
+ }
+
+ this->allow_full_ao_fill_gap = 1;
#ifdef LOG
- printf ("audio_out:loop:pause: I feel sleepy.\n");
+ printf ("audio_out:loop:pause: I feel sleepy.\n");
#endif
- xine_usec_sleep (10000);
+ xine_usec_sleep (10000);
#ifdef LOG
- printf ("audio_out:loop:pause: I wake up.\n");
+ printf ("audio_out:loop:pause: I wake up.\n");
#endif
- break;
- }
- }
+ continue;
}
- /* pthread_mutex_lock( &this->driver_lock ); What is this lock for ? */
+
+
+ pthread_mutex_lock( &this->driver_lock );
delay = this->driver->delay(this->driver);
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);
}
- /* pthread_mutex_unlock( &this->driver_lock ); */
+ pthread_mutex_unlock( &this->driver_lock );
+
/*
* where, in the timeline is the "end" of the
* hardware audio buffer at the moment?
@@ -569,7 +589,7 @@ static void *ao_loop (void *this_gen) {
/*
* calculate gap:
*/
- gap = buf->vpts - hw_vpts;
+ gap = in_buf->vpts - hw_vpts;
#ifdef LOG
printf ("audio_out: hw_vpts : %lld buffer_vpts : %lld gap : %lld\n",
hw_vpts, buf->vpts, gap);
@@ -580,15 +600,14 @@ static void *ao_loop (void *this_gen) {
*/
/* pthread_mutex_lock( &this->driver_lock ); */
- if (gap < (-1 * AO_MAX_GAP) || !buf->num_frames ) {
+ if (gap < (-1 * AO_MAX_GAP) || !in_buf->num_frames ) {
/* drop package */
#ifdef LOG
printf ("audio_out:loop: next fifo\n");
#endif
fifo_append (this->free_fifo, in_buf);
- in_buf = buf = fifo_remove (this->out_fifo);
- bufs_since_sync++;
+ in_buf = NULL;
#ifdef LOG
printf ("audio_out: audio package (vpts = %lld, gap = %lld) dropped\n",
@@ -629,7 +648,7 @@ static void *ao_loop (void *this_gen) {
printf("\n");
}
#endif
- out_buf = prepare_samples(this, buf);
+ out_buf = prepare_samples (this, in_buf);
#if 0
{
int count;
@@ -640,17 +659,23 @@ static void *ao_loop (void *this_gen) {
printf("\n");
}
#endif
+
+ pthread_mutex_lock( &this->driver_lock );
this->driver->write (this->driver, out_buf->mem, out_buf->num_frames );
+ pthread_mutex_unlock( &this->driver_lock );
+
#ifdef LOG
- printf ("audio_out:loop: next fifo\n");
+ printf ("audio_out:loop: next buf from fifo\n");
#endif
fifo_append (this->free_fifo, in_buf);
- in_buf = buf = fifo_remove (this->out_fifo);
- bufs_since_sync++;
-
+ in_buf = NULL;
}
/* pthread_mutex_unlock( &this->driver_lock ); */
}
+
+ if (in_buf)
+ fifo_append (this->free_fifo, in_buf);
+
pthread_exit(NULL);
return NULL;
}
@@ -833,8 +858,6 @@ static void ao_close(ao_instance_t *this) {
audio_buffer_t *audio_buffer;
- printf ("audio_out: stopping thread...\n");
-
if (this->audio_loop_running) {
void *p;
@@ -849,8 +872,6 @@ static void ao_close(ao_instance_t *this) {
this->audio_thread = 0;
}
- printf ("audio_out: thread stopped, closing driver\n");
-
pthread_mutex_lock( &this->driver_lock );
this->driver->close(this->driver);
pthread_mutex_unlock( &this->driver_lock );
@@ -978,7 +999,9 @@ static void ao_flush (ao_instance_t *this) {
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 < num_buffers; i++) {
@@ -986,6 +1009,14 @@ static void ao_flush (ao_instance_t *this) {
fifo_append_int (this->free_fifo, buf);
}
+ /*
+ * make sure ao_loop can savely quit
+ */
+
+ buf = fifo_remove_int (this->free_fifo);
+ buf->num_frames = 0;
+ fifo_append_int (this->out_fifo, buf);
+
this->flush_audio_driver = 1;
this->allow_full_ao_fill_gap = 1;
pthread_mutex_unlock (&this->free_fifo->mutex);