On Mon, Nov 13, 2017 at 11:12:43 +0100, Henrik Eriksson wrote:
On Fri, Nov 10, 2017 at 13:29:43 +0100, Henrik Eriksson wrote:
Is there any documentation/rationale for how pcm_dsnoop works in snd_pcm_{dsnoop_}status? I am particularly wondering about the ordering of the snd_pcm_dsnoop_sync_ptr and the snd_pcm_status call on the slave pcm.
I see occasional spikes (>1000 frames) of difference between the slave pcm hwpointer after the snd_pcm_status call on it and the pointers in the dsnoop pcm, and a correspondingly bad avail count. I suspect the mismatches are due to process scheduling (the slave pcm status is delayed because the application process not running and the hardware progresses during that delay). Does this seem plausible? If so, could the code be simplified to reduce the the number of systemcalls needed? The status of the slave pcm seems to provide much of the information used to sync the pointers. Or is there some other way to get a tighter coupling between the dsnoop status htstamp and avail count?
Or, rather, in snd_pcm_dnsoop_status() would it not make more sense to use the dsnoop->update_tstamp as tstamp in the returned status, at least when the state is SNDRV_PCM_STATE_RUNNING? The returned status->avail count originates from snd_pcm_dsnoop_sync_ptr() and it seems sensible to me that the tstamp would match that.
For background, this is on a machine with not mmap'ed status and control (in pcm_hw.c) and using slowptr in dsnoop.
Well, this change makes the linearity of repeated calls to snd_pcm_status() and calculating status->tstamp - status->avail * {sample rate} better when using dsnoop. Does anyone have any input on if something like this is reasonable? Thanks.
Regards, /henrik
From: Henrik Eriksson henrik.eriksson@axis.com Subject: [PATCH] pcm: dsnoop: use tstamp from ptr sync in status
When snd_pcm_dsnoop_status() syncs the pointers it stores the tstamp of its slave PCM. Since the avail count returned in the status is calculated on the mmap that is synced to the pointers use that tstamp as status->tstamp. This makes the returned avail count and tstamp match closer than if tstamp is fetched from the subsequent status call on the slave PCM, since this status call may be delayed due to the process not being scheduled.
Signed-off-by: Henrik Eriksson henrik.eriksson@axis.com --- src/pcm/pcm_dsnoop.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index 539b6711..c3600e74 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <stddef.h> #include <unistd.h> +#include <stdbool.h> #include <signal.h> #include <string.h> #include <fcntl.h> @@ -184,11 +185,13 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status) { snd_pcm_direct_t *dsnoop = pcm->private_data; snd_pcm_state_t state; + bool synced = false;
switch(dsnoop->state) { case SNDRV_PCM_STATE_DRAINING: case SNDRV_PCM_STATE_RUNNING: snd_pcm_dsnoop_sync_ptr(pcm); + synced = true; break; default: break; @@ -196,6 +199,8 @@ static int snd_pcm_dsnoop_status(snd_pcm_t *pcm, snd_pcm_status_t * status) memset(status, 0, sizeof(*status)); snd_pcm_status(dsnoop->spcm, status); state = snd_pcm_state(dsnoop->spcm); + if (synced) + status->tstamp = dsnoop->update_tstamp; status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state; status->trigger_tstamp = dsnoop->trigger_tstamp; status->avail = snd_pcm_mmap_capture_avail(pcm);