866427bb60
- xine-lib-safe-audio-pause3 patch (kdebug#180339)
133 lines
5.4 KiB
Diff
133 lines
5.4 KiB
Diff
# HG changeset patch
|
|
# User Miguel Freitas <miguelfreitas@users.sourceforge.net>
|
|
# Date 1234834587 10800
|
|
# Node ID 2208e465026c1e54318d36dad8ca180d52fcc318
|
|
# Parent 24a9b3d531419405f71dbcf96da93876769eb990
|
|
Protect audio loop so it cannot write to a paused device (fix
|
|
pause/resume freeze with pulseaudio).
|
|
|
|
diff -r 24a9b3d53141 -r 2208e465026c src/xine-engine/audio_out.c
|
|
--- a/src/xine-engine/audio_out.c Fri Feb 13 18:01:29 2009 +0000
|
|
+++ b/src/xine-engine/audio_out.c Mon Feb 16 22:36:27 2009 -0300
|
|
@@ -243,6 +243,7 @@
|
|
audio_fifo_t *free_fifo;
|
|
audio_fifo_t *out_fifo;
|
|
int64_t last_audio_vpts;
|
|
+ pthread_mutex_t current_speed_lock;
|
|
uint32_t current_speed; /* the current playback speed */
|
|
/* FIXME: replace all this->clock->speed with this->current_speed. we should make
|
|
* sure nobody will change speed without going through xine.c:set_speed_internal */
|
|
@@ -1040,6 +1041,7 @@
|
|
* we must process/free buffers otherwise the entire engine will stop.
|
|
*/
|
|
|
|
+ pthread_mutex_lock(&this->current_speed_lock);
|
|
if ( this->audio_loop_running &&
|
|
(this->clock->speed == XINE_SPEED_PAUSE ||
|
|
(this->clock->speed != XINE_FINE_SPEED_NORMAL &&
|
|
@@ -1055,6 +1057,7 @@
|
|
_x_refcounter_dec(in_buf->stream->refcounter);
|
|
fifo_append (this->free_fifo, in_buf);
|
|
in_buf = NULL;
|
|
+ pthread_mutex_unlock(&this->current_speed_lock);
|
|
continue;
|
|
}
|
|
|
|
@@ -1065,6 +1068,7 @@
|
|
}
|
|
|
|
lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers);
|
|
+ pthread_mutex_unlock(&this->current_speed_lock);
|
|
xine_usec_sleep (10000);
|
|
lprintf ("loop:pause: I wake up.\n");
|
|
continue;
|
|
@@ -1274,6 +1278,7 @@
|
|
fifo_append (this->free_fifo, in_buf);
|
|
in_buf = NULL;
|
|
}
|
|
+ pthread_mutex_unlock(&this->current_speed_lock);
|
|
|
|
/* Give other threads a chance to use functions which require this->driver_lock to
|
|
* be available. This is needed when using NPTL on Linux (and probably PThreads
|
|
@@ -1684,6 +1689,7 @@
|
|
free (this->frame_buf[1]);
|
|
free (this->zero_space);
|
|
|
|
+ pthread_mutex_destroy(&this->current_speed_lock);
|
|
pthread_mutex_destroy(&this->flush_audio_driver_lock);
|
|
pthread_cond_destroy(&this->flush_audio_driver_reached);
|
|
|
|
@@ -1910,8 +1916,15 @@
|
|
if (value != XINE_FINE_SPEED_NORMAL && value != XINE_SPEED_PAUSE && !this->slow_fast_audio )
|
|
this->ao.control(&this->ao, AO_CTRL_FLUSH_BUFFERS, NULL);
|
|
|
|
- this->ao.control(&this->ao,
|
|
- (value == XINE_SPEED_PAUSE) ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL);
|
|
+ if( value == XINE_SPEED_PAUSE ) {
|
|
+ /* current_speed_lock is here to make sure the ao_loop will pause in a safe place.
|
|
+ * that is, we cannot pause writing to device, filling gaps etc. */
|
|
+ pthread_mutex_lock(&this->current_speed_lock);
|
|
+ this->ao.control(&this->ao, AO_CTRL_PLAY_PAUSE, NULL);
|
|
+ pthread_mutex_unlock(&this->current_speed_lock);
|
|
+ } else {
|
|
+ this->ao.control(&this->ao, AO_CTRL_PLAY_RESUME, NULL);
|
|
+ }
|
|
this->current_speed = value;
|
|
if( this->slow_fast_audio )
|
|
ao_update_resample_factor(this);
|
|
@@ -2056,6 +2069,7 @@
|
|
this->driver = driver;
|
|
this->xine = xine;
|
|
this->clock = xine->clock;
|
|
+ this->current_speed = xine->clock->speed;
|
|
this->streams = xine_list_new();
|
|
|
|
/* warning: driver_lock is a recursive mutex. it must NOT be
|
|
@@ -2087,6 +2101,7 @@
|
|
this->discard_buffers = 0;
|
|
this->zero_space = calloc (1, ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */
|
|
|
|
+ pthread_mutex_init( &this->current_speed_lock, NULL );
|
|
pthread_mutex_init( &this->flush_audio_driver_lock, NULL );
|
|
pthread_cond_init( &this->flush_audio_driver_reached, NULL );
|
|
|
|
diff -r 24a9b3d53141 -r 2208e465026c src/xine-engine/xine.c
|
|
--- a/src/xine-engine/xine.c Fri Feb 13 18:01:29 2009 +0000
|
|
+++ b/src/xine-engine/xine.c Mon Feb 16 22:36:27 2009 -0300
|
|
@@ -330,17 +330,20 @@
|
|
|
|
static void set_speed_internal (xine_stream_t *stream, int speed) {
|
|
xine_t *xine = stream->xine;
|
|
+ int old_speed = xine->clock->speed;
|
|
|
|
- if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE)
|
|
+ if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE)
|
|
/* get all decoder and post threads in a state where they agree to be blocked */
|
|
xine->port_ticket->revoke(xine->port_ticket, 0);
|
|
|
|
- if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE)
|
|
+ if (old_speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE)
|
|
/* all decoder and post threads may continue now */
|
|
xine->port_ticket->issue(xine->port_ticket, 0);
|
|
|
|
- stream->xine->clock->set_fine_speed (stream->xine->clock, speed);
|
|
-
|
|
+ if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE)
|
|
+ /* set master clock so audio_out loop can pause in a safe place */
|
|
+ stream->xine->clock->set_fine_speed (stream->xine->clock, speed);
|
|
+
|
|
/* see coment on audio_out loop about audio_paused */
|
|
if( stream->audio_out ) {
|
|
xine->port_ticket->acquire(xine->port_ticket, 1);
|
|
@@ -350,6 +353,10 @@
|
|
|
|
xine->port_ticket->release(xine->port_ticket, 1);
|
|
}
|
|
+
|
|
+ if (old_speed == XINE_SPEED_PAUSE || speed != XINE_SPEED_PAUSE)
|
|
+ /* master clock is set after resuming the audio device (audio_out loop may continue) */
|
|
+ stream->xine->clock->set_fine_speed (stream->xine->clock, speed);
|
|
}
|
|
|
|
|