summaryrefslogtreecommitdiff
path: root/pipewire-alsa
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2020-05-13 12:09:28 +0200
committerWim Taymans <wtaymans@redhat.com>2020-05-13 12:09:28 +0200
commit56730197d9e7a9c27c41e30cfe59bc929f8bfe8e (patch)
treee94e4b538b8a9555b7deeab0b2a5564e7fa6cb56 /pipewire-alsa
parentfefdc26f84f6735131b91ca7c046105af7208204 (diff)
alsa: report xrun
When we record but there is not enough space in the ringbuffer, report xrun.
Diffstat (limited to 'pipewire-alsa')
-rw-r--r--pipewire-alsa/alsa-plugins/pcm_pipewire.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/pipewire-alsa/alsa-plugins/pcm_pipewire.c b/pipewire-alsa/alsa-plugins/pcm_pipewire.c
index 25626113..0e9944f7 100644
--- a/pipewire-alsa/alsa-plugins/pcm_pipewire.c
+++ b/pipewire-alsa/alsa-plugins/pcm_pipewire.c
@@ -64,6 +64,7 @@ typedef struct {
unsigned int activated:1; /* PipeWire is activated? */
unsigned int drained:1;
unsigned int draining:1;
+ unsigned int xrun_detected:1;
snd_pcm_uframes_t hw_ptr;
snd_pcm_uframes_t boundary;
@@ -160,9 +161,15 @@ static int snd_pcm_pipewire_poll_revents(snd_pcm_ioplug_t *io,
static snd_pcm_sframes_t snd_pcm_pipewire_pointer(snd_pcm_ioplug_t *io)
{
snd_pcm_pipewire_t *pw = io->private_data;
+ if (pw->xrun_detected)
+ return -EPIPE;
if (pw->error < 0)
return pw->error;
+#ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA
return pw->hw_ptr;
+#else
+ return pw->hw_ptr % io->buffer_size;
+#endif
}
static int
@@ -274,13 +281,16 @@ snd_pcm_pipewire_process_record(snd_pcm_pipewire_t *pw, struct pw_buffer *b, snd
avail = SPA_MIN(maxsize, *hw_avail * bpf);
index = d[0].chunk->offset;
+ if (maxsize > *hw_avail)
+ pw->xrun_detected = true;
+
do {
avail = SPA_MIN(avail, pw->min_avail * bpf);
offset = index % maxsize;
nbytes = SPA_MIN(avail, maxsize - offset);
ptr = SPA_MEMBER(d[0].data, offset, void);
- pw_log_trace(NAME" %p: %d %d %d %p", pw, nbytes, avail, offset, ptr);
+ pw_log_trace(NAME" %p: %d %ld %d %d %d %p", pw, maxsize, *hw_avail, nbytes, avail, offset, ptr);
nframes = nbytes / bpf;
for (channel = 0; channel < io->channels; channel++) {
@@ -481,6 +491,7 @@ static int snd_pcm_pipewire_prepare(snd_pcm_ioplug_t *io)
done:
pw->hw_ptr = 0;
+ pw->xrun_detected = false;
pw_thread_loop_unlock(pw->main_loop);
@@ -951,6 +962,11 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp, const char *name,
pw->io.poll_fd = pw->fd;
pw->io.poll_events = POLLIN;
pw->io.mmap_rw = 1;
+#ifdef SND_PCM_IOPLUG_FLAG_BOUNDARY_WA
+ pw->io.flags = SND_PCM_IOPLUG_FLAG_BOUNDARY_WA;
+#else
+#warning hw_ptr updates of buffer_size will not be recognized by the ALSA library. Consider to update your ALSA library.
+#endif
if ((err = snd_pcm_ioplug_create(&pw->io, name, stream, mode)) < 0)
goto error;