[alsa-devel] appl_ptr and DMA overrun at end of stream

Jon Smirl jonsmirl at gmail.com
Mon May 11 17:50:22 CEST 2009

On Mon, May 11, 2009 at 11:40 AM, Takashi Iwai <tiwai at suse.de> wrote:
> At Mon, 11 May 2009 11:11:55 -0400,
> Jon Smirl wrote:
>> On Mon, May 11, 2009 at 9:45 AM, Jaroslav Kysela <perex at perex.cz> wrote:
>> > On Mon, 11 May 2009, Jon Smirl wrote:
>> >
>> >>> Right.  This is the value to check in your case.
>> >>
>> >> What do think about redesigning the ALSA DMA interface to support
>> >> detection of over and under run? Leaving the DMA engine in a loop and
>> >> not coordinating with ALSA as to where the valid data is does not seem
>> >> to be a safe way of exchanging data. That interface may be a source of
>> >> the problems pulseaudio is encountering.
>> >>
>> >> A simple solution would be for snd_pcm_period_elapsed() to return
>> >> physical address of the last valid sample. That would let me avoid
>> >> playing with  s->runtime->control->appl_ptr. You could provide the
>> >> same data in the pointer() function.
>> >
>> > More simpler solution is to check the stream state in the low level driver.
>> > If it's in DRAINING state, then end of stream is signaled from the
>> > application and driver might not queue next buffer. We may also add another
>> > callback (or use ioctl callback) to pass this stream state change to the
>> > lowlevel driver immediately, so the driver might react more quickly on this
>> > situation.
>> >
>> Quickness is the wrong way to think about this problem. ALSA knows exactly
>> when it has placed valid data into the buffer.
> Not really.  When the mmap mode is used, the update isn't always
> notified to the driver and the transfer can be completely
> asynchronous.

This seems to me to be a broken design. ALSA is being put into the
position of guessing when the application has supplied new data.
Shouldn't the app be required to make a commit() call after filling in
the data? Without commit it is impossible to detect over/underrun.

>> It's the asynchronous nature of
>> the interface that is the problem. Leaving DMA free running and counting
>> on ALSA to be fast enough to keep data in front of the DMA engine is not
>> a reliable mechanism.
>> Wouldn't it be better to get a synchronous notification and know for sure
>> what data is valid?
> The question is whether you need mmap or not.  If you don't need mmap,
> all the transfer and the buffer update could be much more simplified
> robust.  But if you support mmap, appl_ptr can be updated at any time
> even without the driver interaction, so the async support is
> required like the current model.
>> DRAINING might fix the end of stream, but what if the
>> user space app gets swapped out and can't provide data fast enough?
>> Most reliable for me would be to add enough info so that in my IRQ handler
>> and the pointer() routine, I can check and see whether ALSA has empty/filled
>> the DMA buffers and then only add them to the queue when they are full of
>> valid data.
> Actually, for a hardware like yours, the appl_ptr check could help
> indeed.  Similar implementations are found in
> include/sound/pcm-direct.h.  It's basically for a hardware with own
> buffer to transfer, but a similar idea can be used for the DMA queue
> type devices, and hopefully can be generalized in a better form...
> Takashi

Jon Smirl
jonsmirl at gmail.com

More information about the Alsa-devel mailing list