[alsa-devel] What does snd_pcm_delay() actually return?

Takashi Iwai tiwai at suse.de
Fri Jun 13 17:55:22 CEST 2008


At Fri, 13 Jun 2008 16:25:26 +0200,
Lennart Poettering wrote:
> 
> On Fri, 13.06.08 08:59, Takashi Iwai (tiwai at suse.de) wrote:
> 
> > About the latency, my proposal is like below:
> > 
> > - Renew the definition of hwptr -- make it what you imagned, the
> >   pointer where hardware is reading or has read.
> > 
> >   This won't change anything for PCI drivers, so the impact is
> >   minimal.
> 
> And it would suddenly make the USB drivers do the right thing ;-)

This alone wouldn't :)

> OTOH I am not a big fan of this solution, since the delay in
> "snd_pcm_delay()" kind of suggests that it is useful for time
> synchronization.

Yes, snd_pcm_delay() is the API for synchronization, as even now it
explicitly defines as the delay from the position currently being
played.

> > - Add some new API functions,
> >   * To give the accuracy of the position inquiry (optional)
> > 
> >     This requires some new kernel <-> user-space stuff.
> 
> I'd really like to have this. Only when I know this I can know how
> near to the current hw_ptr I can actually still make changes in the
> playback buffer.

One question is what quantity should it be.
In most cases, it's simply a flag -- that is, the hwptr is updated
only at the period boundary.  But, this isn't maybe appropriate,
e.g. if we introduce the stream control via (hr)timer.


> >   * To query the known latency
> > 
> >     Ditto, or we may reuse snd_pcm_hw_params_fifo_size()?
> 
> I am not a fan of snd_pcm_hw_params_fifo_size() because the 'fifo'
> latency is dynamic in the network case, it changes all the time with
> the level of network congestion. However if something is part of
> hw_params it is supposed to stay fixed, right? 
> 
> Hence I'd rather prefer if we let snd_pcm_hw_params_fifo_size() rest
> in peace.

Agreed.  A new API sounds saner to me.


> My personal favourite solution would actually be to have a new call
> that allows you to query *all* timing related values
> *atomically*. Why? different programs need different timing
> information from ALSA. Also, timing information happens to change all
> the time. If we just export two basic values, than people might end up
> doing arithmetics on them, in the risk the two values are not
> consistent with each other, since between querying them some time
> already passed. So, what I would suggest is this:
> 
>   typedef enum snd_pcm_timing {
>         SND_PCM_TIMING_ABSOLUTE_WRITE,
>         SND_PCM_TIMING_ABSOLUTE_READ,
>         SND_PCM_TIMING_ABSOLUTE_HEAR,
>         SND_PCM_TIMING_WRITE_TO_READ,
>         SND_PCM_TIMING_WRITE_TO_HEAR,
>         SND_PCM_TIMING_READ_TO_HEAR,
>         SND_PCM_TIMING_CAN_WRITE,
>         SND_PCM_TIMING_LEFT_TO_PLAY
>   } snd_pcm_timing_t;
> 
>   snd_pcm_sframes_t snd_pcm_get_timing(snd_pcm_t *pcm, snd_pcm_timing_t timing);
> 
> The user would just pass which of the timing values he needs. The
> meaning would be:
> 
>         ABSOLUTE_WRITE: the current absolute write counter in samples, since the device was opened.
>         ABSOLUTE_READ:  the current absolute read counter in samples, since the device was opened.
>         ABSOLUTE_HEAR:  the current absolute hear counter in samples, since the device was opened.
>         WRITE_TO_READ:  the current fill level of the playback buffer
>         WRITE_TO_HEAR:  if i write a sample immediately after this call, how much time takes it to be played.
>         READ_TO_HEAR:   the 'fifo' latency, i.e. the time that passes
>                         after a sample was read form the playback buffer that it is
>                         actually played.
>         CAN_WRITE:      how much can be written into the buffer right
>                         now  (buffer_size - WRITE_TO_READ)
>         LEFT_TO_PLAY:   similar to WRITE_TO_HEAR but callable *after* we
>                         wrote something, and it will return how much
>                         of what we wrote has not been heard yet. In
>                         contrast to WRITE_TO_HEAR this will return 0 eventually.        

Hmm... at a first glance, this already looks complicated.

What about just providing three pointers: curr_ptr, hw_ptr and
appl_ptr?  curr_ptr corresponds to the point being played, and hw_ptr
is the point where the data was already sent to h/w, and appl_ptr is
the point where the data is filled by user.  The above definitions are
all combinations of these pointers.

I really don't understand why we need to hide hw_ptr and appl_ptr in
the current API.  To me, exposing these points is much more
straightforward.

In addition, there will be an API to provide the position
granularity as mentioned in the above.  But, this can be a different
thing from the pointer APIs.


Takashi


More information about the Alsa-devel mailing list