All of lore.kernel.org
 help / color / mirror / Atom feed
* PCM buffering ussues ( or probably the lack of understanding )
@ 2013-04-20  7:13 marcelg
  2013-04-20  7:52 ` Lars-Peter Clausen
  0 siblings, 1 reply; 4+ messages in thread
From: marcelg @ 2013-04-20  7:13 UTC (permalink / raw)
  To: alsa-devel

I am working on a PCM driver, have some issues and thing which are 
unclear to me, hopefully somebody here can clarify something for me.

My PCM driver is straigh forward:

- Copy callback copies the frames received in the callback into a small 
ringbuffer and starts a DMA transfer to the hardware.
- DMA interrupt each times take the next chunk from the ringbuffer.
- In the DMA interrupt the number of frames is counted, if te number >= 
period_size reported in runtime_struct   pcm_period_elapsed() is called.
- the pointer which is read by the pcm_pointer() callback is updated in 
each DMA interrupt.

When using mplayer this works without problems, however with other 
applications like mpg123 its causes a lot of problems, for some reaosns 
I do not understand yet.
It has something to do with buffer handling.


basically in the cm driver I can influence a few parameters:

periods_min/periods_max
period_bytes_min, period_bytes_max
buffer_size  ( should be sufficient to hold periods_max with 
period_bytes_max I assume )

As far as I understand periods_min/periods_max is the size (number of 
buffer entries) of the internal ringbuffer Alsa uses.
- Why is there both a min and a max ?  How is chosen what will be used ?
- Currently my period_min is set to 1 and my period_max  set to 4, If I 
increase the period_max value it does not start properly, it seems  that 
the samples are not deliverered in time.
   Is there any explanation for this,   does the Alsa layer not any 
pre-buffering before the first copy() is called ?
- Is there any advice / guidline for period min/max values ?  I checked 
sourecs of severl drivers, some use 1 and some use values like 32 or 
more for period_max.

The same applies to buffer_bytes min/max, currently my min is set to 
128bytes , max to 2kB, larger values of max seem to cause more problems.

 From the documentation I understand that it does not matter if 
pcm_period_elapsed()  is not always called,  How dows the ALSA layer 
then know how many samples are played.
the pointer value read the pcm_pointer()  only counts from 
[0..period_max]  so what if 2 or more calls to period_elapsed()  are 
skipped ?

Suppose I want to have some buffering inside my pcm driver, how will I 
be able to get some samples in advance before starting playback ? Can I 
just call pcm_period_elapsed() a few times in  a row to get the buffer 
filled
before starting the actual playcback, or does this cause side effects ?

I noticed that the number of frames passed to pcm_copy is often less 
than the periods_size, is this determined by the application ?


Lots of questions, but I try to understand the odd behaviour with 
certain applications ( and the best settings for a pcm driver which will 
work with most applications )

Any help would be appreciated.

Marcel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PCM buffering ussues ( or probably the lack of understanding )
  2013-04-20  7:13 PCM buffering ussues ( or probably the lack of understanding ) marcelg
@ 2013-04-20  7:52 ` Lars-Peter Clausen
  2013-04-20  8:46   ` Clemens Ladisch
       [not found]   ` <5172750A.4030805@quicknet.nl>
  0 siblings, 2 replies; 4+ messages in thread
From: Lars-Peter Clausen @ 2013-04-20  7:52 UTC (permalink / raw)
  To: marcelg; +Cc: alsa-devel

On 04/20/2013 09:13 AM, marcelg wrote:
> I am working on a PCM driver, have some issues and thing which are unclear
> to me, hopefully somebody here can clarify something for me.
> 
> My PCM driver is straigh forward:

It's always easier to comment on potential issues if you provide the code.


> 
> - Copy callback copies the frames received in the callback into a small
> ringbuffer and starts a DMA transfer to the hardware.

If you have DMA support your probably shouldn't implement the copy
callback, but rather let also write directly to your hardware buffer.

> - DMA interrupt each times take the next chunk from the ringbuffer.
> - In the DMA interrupt the number of frames is counted, if te number >=
> period_size reported in runtime_struct   pcm_period_elapsed() is called.
> - the pointer which is read by the pcm_pointer() callback is updated in each
> DMA interrupt.
> 
> When using mplayer this works without problems, however with other
> applications like mpg123 its causes a lot of problems, for some reaosns I do
> not understand yet.
> It has something to do with buffer handling.
> 
> 
> basically in the cm driver I can influence a few parameters:
> 
> periods_min/periods_max
> period_bytes_min, period_bytes_max
> buffer_size  ( should be sufficient to hold periods_max with
> period_bytes_max I assume )
> 
> As far as I understand periods_min/periods_max is the size (number of buffer
> entries) of the internal ringbuffer Alsa uses.

There is no ALSA internal ringbuffer. The only buffer is the buffer your
driver allocates.

> - Why is there both a min and a max ?  How is chosen what will be used ?

This expresses the hardware limitations. The minimum and maximum number of
periods per buffer supported by the hardware. When starting playback/capture
userspace may choose any number between min and max for the actual number of

> - Currently my period_min is set to 1 and my period_max  set to 4, If I
> increase the period_max value it does not start properly, it seems  that the
> samples are not deliverered in time.
>   Is there any explanation for this,   does the Alsa layer not any
> pre-buffering before the first copy() is called ?

Well that probably means there is a bug in your driver so that it does not
support more than 4 periods.

> - Is there any advice / guidline for period min/max values ?  I checked
> sourecs of severl drivers, some use 1 and some use values like 32 or more
> for period_max.
> 

Yes, set them according to the limitations of your hw.

> The same applies to buffer_bytes min/max, currently my min is set to
> 128bytes , max to 2kB, larger values of max seem to cause more problems.
> 

Same here.

> From the documentation I understand that it does not matter if
> pcm_period_elapsed()  is not always called,  How dows the ALSA layer then
> know how many samples are played.
> the pointer value read the pcm_pointer()  only counts from [0..period_max] 
> so what if 2 or more calls to period_elapsed()  are skipped ?

pcm_pointer goes from 0 to buffer_size. Since you usually have multiple
periods per buffer it is possible to recover from a situation where
pcm_period_elapsed() was skipped.

> 
> Suppose I want to have some buffering inside my pcm driver, how will I be
> able to get some samples in advance before starting playback ? Can I just
> call pcm_period_elapsed() a few times in  a row to get the buffer filled
> before starting the actual playcback, or does this cause side effects ?
> 

Why'd you want to do that?

- Lars

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PCM buffering ussues ( or probably the lack of understanding )
  2013-04-20  7:52 ` Lars-Peter Clausen
@ 2013-04-20  8:46   ` Clemens Ladisch
       [not found]   ` <5172750A.4030805@quicknet.nl>
  1 sibling, 0 replies; 4+ messages in thread
From: Clemens Ladisch @ 2013-04-20  8:46 UTC (permalink / raw)
  To: Lars-Peter Clausen; +Cc: alsa-devel, marcelg

Lars-Peter Clausen wrote:
> pcm_pointer goes from 0 to buffer_size.

Actually, from 0 to buffer_size - 1.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PCM buffering ussues ( or probably the lack of understanding )
       [not found]   ` <5172750A.4030805@quicknet.nl>
@ 2013-04-20 11:17     ` Lars-Peter Clausen
  0 siblings, 0 replies; 4+ messages in thread
From: Lars-Peter Clausen @ 2013-04-20 11:17 UTC (permalink / raw)
  To: marcelg; +Cc: Linux-ALSA

On 04/20/2013 12:59 PM, marcelg wrote:
> Lars Peter,
> 
> Thanks for your reply.
> 
> Some things are more clear now, however one issue I still wonder.
> 
> 
> Quote
> 
> "
>> Suppose I want to have some buffering inside my pcm driver, how will I be
>> able to get some samples in advance before starting playback ? Can I just
>> call pcm_period_elapsed() a few times in  a row to get the buffer filled
>> before starting the actual playcback, or does this cause side effects ?
>>
> Why'd you want to do that?
> "
> 
> 
> If Alsa is not having an internal buffer as you pointed out. An my driver
> for example advertises
> min periods = 1  and max_periods = 10.   Then it means my drivers is capable
> of buffering up to 10 periods.
> 
> However what I notice is that the Alsa layer pcm_copy()  always supplies
> "period_bytes" after each call to period_elapsed()
> 
> This would imply that even my driver is able to buffer 10 periods, it never
> receives more data as one period, because I call period_elapsed()
> as soon as the data is consumed.


The ALSA core keeps track of how many bytes are available in your buffer. It
will supply your driver with as many bytes as there is space in the buffer.
So if you start playback you should see it supplying you more than one
period worth of bytes. Once the buffer is full you'll naturally only get one
new period of each period that has elapsed.

But as I said before if you don't do anything other then copying data to
your buffer in the copy callback, you should probably get rid of the copy
callback altogether and let ALSA take care of writing the data to your
buffer. This will also allow you to use for example mmap.

- Lars

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-04-20 11:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-20  7:13 PCM buffering ussues ( or probably the lack of understanding ) marcelg
2013-04-20  7:52 ` Lars-Peter Clausen
2013-04-20  8:46   ` Clemens Ladisch
     [not found]   ` <5172750A.4030805@quicknet.nl>
2013-04-20 11:17     ` Lars-Peter Clausen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.