[alsa-devel] Intel HDA + HDMI - snd_pcm_drain buggy behaviour.
Sander Jansen
s.jansen at gmail.com
Mon Feb 17 03:52:39 CET 2014
Ok. Never mind. I was under the false impression that snd_pcm_drain would
be able to handle partially filled periods. Making sure the last write
fills at least a period seemed to have solved the issue.
On Sun, Feb 16, 2014 at 2:26 PM, Sander Jansen <s.jansen at gmail.com> wrote:
> Further investigation on my part I noticed a couple of mistakes I made
> myself.
>
> 1. snd_pcm_drain() doesn't block in non-blocking mode. I fixed my code to
> account for this now.
> 2. snd_pcm_drain() doesn't block indefinitely in blocking mode. I must
> have accidently put in a infinite loop somewhere myself.
>
> That leaves still with one unresolved issue, which is that calling
> snd_pcm_drain() does indeed work in both blocking and non-blocking, but I'm
> still hearing part of the audio that was already played before. I assume
> this is some data in the ringbuffer that hasn't been overwritten by any new
> data. I have been able to reproduce this on another PC (Intel G45 chipset)
> as well (snd_intel_hda as well, but with analog output) so I don't think
> it's HDMI related.
>
>
> This is my drain code:
>
> snd_pcm_state_t state = snd_pcm_state(handle);
> if (state==SND_PCM_STATE_RUNNING) {
>
> /// block while draining
> //if ((result=snd_pcm_nonblock(handle,0))<0) {
> // printf("[alsa] failed to set blocking mode. Reason:
> %s\n",snd_strerror(result));
> // return;
> // }
>
> result=snd_pcm_drain(handle);
> if (result==-EAGAIN) {
> printf("[alsa] waiting for drain\n");
> while(snd_pcm_state(handle)==SND_PCM_STATE_DRAINING){
> FXThread::sleep(500000000); // 50ms
> }
> printf("[alsa] drain complete. State:
> %s\n",snd_pcm_state_name(snd_pcm_state(handle)));
> }
> else if (result<0) {
> printf("[alsa] drain failed. Reason: %s\n",snd_strerror(result));
> }
> else {
> printf("[alsa] drain complete\n");
> }
> }
>
> Anything else I'm doing wrong?
>
> Thanks,
>
> Sander
>
>
> On Sat, Feb 15, 2014 at 6:44 PM, Sander Jansen <s.jansen at gmail.com> wrote:
>
>> All,
>>
>> When I play regular PCM audio through the HDMI that's connected to my
>> amplifier I noticed buggy behaviour when using the snd_pcm_drain() call.
>> From my understanding of ALSA, during playback snd_pcm_drain() normally
>> blocks until the playback buffer is empty.
>>
>> Here's what I'm experiencing:
>>
>> a. If the PCM handle is in BLOCKING mode, the snd_pcm_drain() function
>> will block indefinitely (I've waited 30 seconds, before I gave up).
>>
>> b. In NON-BLOCKING mode, the first call to snd_pcm_drain results in a
>> " Resource temporarily unavailable", subsequent call works but the pcm
>> state has changed to DRAINING and takes about 1 sec to change to SETUP.
>> Even though the audio has less than 0.5 seconds of actual playback left.
>>
>> So to make it work, I changed my single snd_pcm_drain() call into the
>> following pseudo code:
>> while(state==RUNNING && snd_pcm_drain()<0) {
>> state=snd_pcm_state()
>> }
>>
>> while(state==DRAINING && sleep(100)){
>> state=snd_pcm_state()
>> }
>>
>> Even though this seem to "sort of work", another problem with this
>> approach I've noticed, is that part of the beginning of the playback buffer
>> may be replayed at the end of the drain:
>>
>> 1. start playback at beginning of file
>> 2. seek to close to the end of the file (snd_pcm_drop() gets called)
>> 3. end of file reached, drain gets called, hear the end of the song +
>> part of the beginning again?
>>
>> So I'm wondering whether this may be related to the drain issue I've
>> noticed. I've attached the alsa-info.
>>
>> Thanks,
>>
>> Sander
>>
>>
>>
>
More information about the Alsa-devel
mailing list