diff mbox series

no audio when using the dshare plugin with ALSA driver using indirect PCM data transfer

Message ID 20200517182241.7361FF801A3@alsa1.perex.cz
State Superseded
Headers show
Series no audio when using the dshare plugin with ALSA driver using indirect PCM data transfer | expand

Commit Message

GitHub issues - opened May 17, 2020, 6:22 p.m. UTC
alsa-project/alsa-lib issue #51 was edited from bondagit:

Hi all,

I am currently working on an open source project on GitHub [AES67 Linux daemon with WebUI](https://github.com/bondagit/aes67-linux-daemon).
This project uses the [Merging Technologies ALSA RAVENNA/AES67 Linux Driver](https://bitbucket.org/MergingTechnologies/ravenna-alsa-lkm/src/master).
This ALSA driver does support the mmap access using indirect PCM data transfer.

The driver is working properly when used directly but not when it's used via the **dshare** plugin.
See issue [No sound using dshare in asound.conf](https://github.com/bondagit/aes67-linux-daemon/issues/7) in the AES67 Linux daemon project.

For all my tests I used the **Linux Kernel 5.3.0-51** and the **alsa-lib v1.1.9** but I get same results with most recent kernel and with the **alsa-lib** on the master branch.
My _.asoundrc_ configuration is the following:
```
pcm.aes67 {
        type hw
        card 1
        device 0
        #sync_ptr_ioctl true
}

pcm_slave.nforce {
    pcm "aes67"
    channels 2
    rate 48000
    buffer_size 24576  
    period_size 48
    format S24_3LE
    periods 0
    period_time 1000
}

pcm.ch12 {
   type dshare
   ipc_key 47110815
   slave nforce
   bindings.0 0
   bindings.1 1
   #slowptr true
}
```

Basically when I playback a sample PCM audio using the ALSA RAVENNA/AES67 HW device directly via mmap I get a proper playout. 
Ex: `aplay -D hw:1 sample.raw -M`
But if I do the same using the dshare plugin I do always get no audio (silence):
Ex: `aplay -D ch12 sample.raw -M`

After a number of tests trying to compare the behavior of the **alsa-lib** when using the ALSA driver directly (aplay -D hw:1) and when using the plugin (aplay -D ch12) I realized that in the second case the  **SNDRV_PCM_IOCTL_SYNC_PTR ioctl**  is never triggered in the audio loop by the **alsa-lib** . (I could easily capture this by using strace).
I would expect the `snd_pcm_dshare_mmap_commit() `function of **alsa-lib** to invoke the above ioctl but this is not happening.
The result is that in the ALSA driver the **ack()** callback is not called to indicate that the **appl_ptr** is updated and this causes the problem we have.

In the Linux kernel when the ioctl SNDRV_PCM_IOCTL_SYNC_PTR is called the following functions are called: 
`snd_pcm_sync_ptr() -> pcm_lib_apply_appl_ptr() -> substream->ops->ack() `
but as stated above this is happening only if the ALSA driver is used directly (aplay -D hw:1) and not when it's used via the plugin (aplay -D ch12).

I could fix the issue applying the following temporary fix to the **alsa-lib**:
```
```
The fix basically triggers the call to the `snd_pcm_hw_mmap_commit()` function of the slave pcm of the dshare plugin. This function invokes the ` issue_applptr() ` and then the `sync_ptr1()` that finally calls the SNDRV_PCM_IOCTL_SYNC_PTR ioctl to update the **appl_ptr** in the kernel.

After applying this fix I can properly hear the audio.

I am available to provide any additional information and to do additional tests.
Since I don't have much experience with the **alsa-lib** it can be that the problem is related to some misconfiguration but at present I managed to solve the issue only by applying the above fix.

Thanks in advance for your help.

Issue URL     : https://github.com/alsa-project/alsa-lib/issues/51
Repository URL: https://github.com/alsa-project/alsa-lib
diff mbox series

Patch

diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c
index f135b5df..1f103414 100644
--- a/src/pcm/pcm_dshare.c
+++ b/src/pcm/pcm_dshare.c
@@ -562,6 +562,7 @@  static snd_pcm_sframes_t snd_pcm_dshare_mmap_commit(snd_pcm_t *pcm,
                /* clear timer queue to avoid a bogus return from poll */
                if (snd_pcm_mmap_playback_avail(pcm) < pcm->avail_min)
                        snd_pcm_direct_clear_timer_queue(dshare);
+               dshare->spcm->fast_ops->mmap_commit(dshare->spcm, offset, size);
        }
        return size;
 }