[alsa-devel] appl_ptr and DMA overrun at end of stream
Jon Smirl
jonsmirl at gmail.com
Mon May 11 18:28:48 CEST 2009
On Mon, May 11, 2009 at 11:58 AM, Takashi Iwai <tiwai at suse.de> wrote:
> At Mon, 11 May 2009 11:50:22 -0400,
> Jon Smirl wrote:
>>
>> 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.
>
> The commit updates the mmapped control data (so that it works even
> without the context switch) if the architecture supports. In other
> cases, a commit issues an explicit sync ioctl.
>
> Actually it should be possible to disable the mmap-control mode
> explicitly, but right now it's not done from the driver side but only
> checks the architecture.
Shared memory is another solution that doesn't involve context switches.
The app can update it's valid pointer in shared memory.
My IRQ will call snd_pcm_period_elapsed().
snd_pcm_period_elapsed() can find the updated valid pointer,
convert it to a physical address and leave it in a shared structure.
When snd_pcm_period_elapsed() returns, my IRQ can get to
the pointer and submit the necessary buffers.
What's missing is an official way of accessing
s->runtime->control->appl_ptr from the low level driver. We're
implementing a ring buffer. In a ring buffer I have to know where both
pointers are in order to detect over/under run. I also don't
understand why this is specific to my hardware, every DMA
implementation should need these two pointers.
>
>
> Takashi
>
--
Jon Smirl
jonsmirl at gmail.com
More information about the Alsa-devel
mailing list