On Tue, 16 Nov 2010, Clemens Ladisch wrote:
> Jaroslav Kysela wrote:
>>> pl bossart wrote:
>>>> Here's the second set of patches based on feedback from Takashi,
>>>> Jaroslav and Clemens. Hope this is fine now.
>>
>> The problem in the kernel side is that there is no ring buffer boundary
>> check using system jiffies. Without this check, the actual implementation
>> does not guarantee the consistency of hw_ptr.
>
> How about this?
The patch bellow looks good. I would probably add some lightweight
condition on top like:
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2 + 1)
goto no_delta_check;
But it's just an optimization. Please, commit.
Thanks,
Jaroslav
> --8<---------------------------------------------------------------->8--
> ALSA: pcm: detect xruns in no-period-wakeup mode
>
> When period wakeups are disabled, successive calls to the pointer update
> function do not have a maximum allowed distance, so xruns cannot be
> detected with the pointer value only.
>
> To detect xruns, compare the actually elapsed time with the time that
> should have theoretically elapsed since the last update. When the
> hardware pointer has wrapped around due to an xrun, the actually elapsed
> time will be too big by about hw_ptr_buffer_jiffies.
>
> Signed-off-by: Clemens Ladisch <clemens@xxxxxxxxxx>
> ---
> sound/core/pcm_lib.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> --- alsa-kernel/sound/core/pcm_lib.c
> +++ alsa-kernel/sound/core/pcm_lib.c
> @@ -374,9 +374,23 @@ static int snd_pcm_update_hw_ptr0(struct
> (unsigned long)runtime->hw_ptr_base);
> }
>
> - /* without period interrupts, there are no regular pointer updates */
> - if (runtime->no_period_wakeup)
> + if (runtime->no_period_wakeup) {
> + /*
> + * Without regular period interrupts, we have to check
> + * the elapsed time to detect xruns.
> + */
> + jdelta = jiffies - runtime->hw_ptr_jiffies;
> + hdelta = jdelta - delta * HZ / runtime->rate;
> + while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
> + delta += runtime->buffer_size;
> + hw_base += runtime->buffer_size;
> + if (hw_base >= runtime->boundary)
> + hw_base = 0;
> + new_hw_ptr = hw_base + pos;
> + hdelta -= runtime->hw_ptr_buffer_jiffies;
> + }
> goto no_delta_check;
> + }
>
> /* something must be really wrong */
> if (delta >= runtime->buffer_size + runtime->period_size) {
-----
Jaroslav Kysela <perex@xxxxxxxx>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
[ALSA User]
[Linux Audio Users]
[Kernel Archive]
[Asterisk PBX]
[Photo Sharing]
[Linux Sound]
[Video 4 Linux]
[Gimp]
[Yosemite News]