summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2012-05-03 19:22:39 +0200
committerGravatar waker <wakeroid@gmail.com>2012-05-03 19:23:08 +0200
commit52be1f66c294caeb628d4d46d0045473403841d5 (patch)
tree9b410132a6679e54205f24c39c32bf451cebe127 /plugins
parentef1c07cc3bbd19b9f75f3a7d962c619a3952ce8a (diff)
[by Martin Panter <vadmium à gmail·com>]
Retry with the same data after recovering from an underrun or other error The palsa_callback() function seems to limit the rate it returns data, and if a buffer of data is dropped because snd_pcm_writei() failed, the data rate is not fast enough to keep up with ALSA and another buffer underrun occurs. This could cause an indefinite cycle, and the audio would sound slighly choppy and sped up. If the original data is retried, the ALSA buffer eventually tends to become full; perhaps the rate limit is a little faster than real time. When playback continues on to an MP3 file cued in the playlist, the MP3 seems to be scanned before it starts playing. If the scanning takes too long, in my case because the MP3 file is mounted with SSHFS over wifi, it causes a buffer underrun. The code below could also be inserted, just before the snd_pcm_writei() call, to artificially cause an underrun a few seconds into playback: static int n = 0; ++n; if (n >= 200 && n < 300) { trace ("dropping %i\n", n); err = 0; } else err = snd_pcm_writei (...);
Diffstat (limited to 'plugins')
-rw-r--r--plugins/alsa/alsa.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/plugins/alsa/alsa.c b/plugins/alsa/alsa.c
index 618465b7..08fbc9b8 100644
--- a/plugins/alsa/alsa.c
+++ b/plugins/alsa/alsa.c
@@ -613,6 +613,9 @@ palsa_thread (void *context) {
continue;
}
LOCK;
+ char buf[period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels];
+ int bytes_to_write = 0;
+
/* find out how much space is available for playback data */
snd_pcm_sframes_t frames_to_deliver = snd_pcm_avail_update (audio);
@@ -624,12 +627,13 @@ palsa_thread (void *context) {
break;
}
err = 0;
- char buf[period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels];
- UNLOCK; // holding a lock here may cause deadlock in the streamer
- int bytes_to_write = palsa_callback (buf, period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels);
- LOCK;
- if (alsa_terminate) {
- break;
+ if (!bytes_to_write) {
+ UNLOCK; // holding a lock here may cause deadlock in the streamer
+ bytes_to_write = palsa_callback (buf, period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels);
+ LOCK;
+ if (OUTPUT_STATE_PLAYING != state || alsa_terminate) {
+ break;
+ }
}
if (bytes_to_write >= (plugin.fmt.bps>>3) * plugin.fmt.channels) {
@@ -643,6 +647,7 @@ palsa_thread (void *context) {
else {
UNLOCK;
usleep (10000);
+ bytes_to_write = 0;
LOCK;
continue;
}
@@ -669,9 +674,10 @@ palsa_thread (void *context) {
//}
snd_pcm_prepare (audio);
snd_pcm_start (audio);
- continue;
}
+ continue;
}
+ bytes_to_write = 0;
frames_to_deliver = snd_pcm_avail_update (audio);
}
UNLOCK;