From 543a9eac5d857c5a629e81c37d97102de537516a Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Fri, 23 Feb 2018 10:28:51 +0100 Subject: [PATCH] pcm: ioplug: Use boundary for wrap around if requested by the IO plugin Without this changes an IO plugin is not able to report that buffer_size frames were read from the buffer. When the buffer was full this is a valid action and has not to be handled as an under run. For example when the hw_ptr will be updated with hw_ptr += buffer_size and it is using the buffer_size as wrap around hw_ptr %= buffer_size would result in the same value as before the add operation. Signed-off-by: Timo Wischer Signed-off-by: Takashi Iwai --- include/pcm_ioplug.h | 5 +++++ src/pcm/pcm_ioplug.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/pcm_ioplug.h b/include/pcm_ioplug.h index 1c845940..e75f973e 100644 --- a/include/pcm_ioplug.h +++ b/include/pcm_ioplug.h @@ -65,6 +65,8 @@ typedef snd_pcm_ioplug_callback snd_pcm_ioplug_callback_t; */ #define SND_PCM_IOPLUG_FLAG_LISTED (1<<0) /**< list up this PCM */ #define SND_PCM_IOPLUG_FLAG_MONOTONIC (1<<1) /**< monotonic timestamps */ +/** hw pointer wrap around at boundary instead of buffer_size */ +#define SND_PCM_IOPLUG_FLAG_BOUNDARY_WA (1<<2) /* * Protocol version @@ -133,6 +135,9 @@ struct snd_pcm_ioplug_callback { int (*stop)(snd_pcm_ioplug_t *io); /** * get the current DMA position; required, called inside mutex lock + * \return buffer position up to buffer_size or + * when #SND_PCM_IOPLUG_FLAG_BOUNDARY_WA flag is set up to boundary or + * a negative error code for Xrun */ snd_pcm_sframes_t (*pointer)(snd_pcm_ioplug_t *io); /** diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c index 7a782e68..9970646f 100644 --- a/src/pcm/pcm_ioplug.c +++ b/src/pcm/pcm_ioplug.c @@ -42,7 +42,7 @@ const char *_snd_module_pcm_ioplug = ""; typedef struct snd_pcm_ioplug_priv { snd_pcm_ioplug_t *data; struct snd_ext_parm params[SND_PCM_IOPLUG_HW_PARAMS]; - unsigned int last_hw; + snd_pcm_uframes_t last_hw; snd_pcm_uframes_t avail_max; snd_htimestamp_t trigger_tstamp; } ioplug_priv_t; @@ -56,13 +56,18 @@ static void snd_pcm_ioplug_hw_ptr_update(snd_pcm_t *pcm) hw = io->data->callback->pointer(io->data); if (hw >= 0) { - unsigned int delta; - if ((unsigned int)hw >= io->last_hw) + snd_pcm_uframes_t delta; + + if ((snd_pcm_uframes_t)hw >= io->last_hw) delta = hw - io->last_hw; - else - delta = pcm->buffer_size + hw - io->last_hw; + else { + const snd_pcm_uframes_t wrap_point = + (io->data->flags & SND_PCM_IOPLUG_FLAG_BOUNDARY_WA) ? + pcm->boundary : pcm->buffer_size; + delta = wrap_point + hw - io->last_hw; + } snd_pcm_mmap_hw_forward(io->data->pcm, delta); - io->last_hw = hw; + io->last_hw = (snd_pcm_uframes_t)hw; } else io->data->state = SNDRV_PCM_STATE_XRUN; } -- 2.11.0