[alsa-devel] alsa timestamps

Takashi Iwai tiwai at suse.de
Wed Nov 21 11:33:50 CET 2007


At Tue, 20 Nov 2007 18:07:25 +0200,
Heikki Lindholm wrote:
> 
> Takashi Iwai kirjoitti:
> > At Tue, 20 Nov 2007 16:54:32 +0200,
> > Heikki Lindholm wrote:
> >> Takashi Iwai kirjoitti:
> >>> At Mon, 19 Nov 2007 15:41:46 +0200,
> >>> Heikki Lindholm wrote:
> >>>> Jaroslav Kysela kirjoitti:
> >>>>> On Mon, 19 Nov 2007, Heikki Lindholm wrote:
> >>>>>
> >>>>>> Heikki Lindholm kirjoitti:
> >>>>>>> Hello list,
> >>>>>>>
> >>>>>>> I took up some old dusty code of mine that uses snd_pcm_state followed 
> >>>>>>> by snd_pcm_status_get_tstamp when in capture mode. The code used to 
> >>>>>>> work, but now the returned timestamps are all zeroes. Is there some API 
> >>>>>>> change done recently or is the whole timestamping deprecated or 
> >>>>>>> something? I've tried with different drivers on ubuntu's alsa .14 and 
> >>>>>>> gentoo's .14. I've also tried mmap'ed and r/w modes, and I'm setting the 
> >>>>>>> TSTAMP_MMAP sw param.
> >>>>>> I figured out that this doesn't happen when using hw:x,y devices. Is it 
> >>>>>> a documented feature that some (software?) devices don't fill in timestamps?
> >>>>> I think that it should be fixed. Could you send us 'snd_pcm_dump()' for a 
> >>>>> non-working device? It's probably ommited code in direct pcm plugins (dmix 
> >>>>> & etc.).
> >>>> Here goes. The driver is snd_aoa. It seems as if the timestamp mode 
> >>>> isn't propagated to the hw device.
> >>> AFAIK, the time-stamp mode isn't handled properly with direct plugins
> >>> because of its nature.  Since the direct plugins share the same PCM
> >>> hardware instance with multiple processes, you cannot change the
> >>> parameter arbitrarily from a single client.
> >>>
> >>> We may implement an emulation in alsa-lib instead, though...
> >> For the time being, is there any other way of determining whether a pcm 
> >> supports time stamps than just trying out and seeing if zero is all that 
> >> comes out?
> > 
> > Hmm, at the second look at the dmix/dsnoop code, it has some lines
> > that actually update the timestamp value (as emulation).  So,
> > basically it should work.  Maybe some other parts are broken...
> > Do you have a small test case code just for checking?
> 
> Attached a test case that I just wrote. Seems I need it anyway since 
> drivers are acting bogus, too. On a Power Mac G5, using snd_aoa, running 
> the program with
> ./alsatest hw:0,0 1024
> produces good timestamps whereas running with
> ./alsatest default 1024
> produces zeros (the second param is period size).
> I also observed the same behaviour on a bog standard x86, with SB Live, 
> I think..

Thanks.  Actually it's a bug in alsa-lib.  The patch below should fix
the problem.  I'll push it to the HG tree.


Takashi

diff -r 39d34d6a4587 src/pcm/pcm_direct.c
--- a/src/pcm/pcm_direct.c	Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_direct.c	Wed Nov 21 12:06:52 2007 +0100
@@ -1001,6 +1001,17 @@ int snd_pcm_direct_initialize_slave(snd_
 		return ret;
 	}
 
+	/* set timestamp mode to MMAP
+	 * the slave timestamp is copied appropriately in dsnoop/dmix/dshare
+	 * based on the tstamp_mode of each client
+	 */
+	ret = snd_pcm_sw_params_set_tstamp_mode(spcm, sw_params,
+						SND_PCM_TSTAMP_MMAP);
+	if (ret < 0) {
+		SNDERR("unable to tstamp mode MMAP");
+		return ret;
+	}
+
 	if (dmix->type != SND_PCM_TYPE_DMIX)
 		goto __skip_silencing;
 
diff -r 39d34d6a4587 src/pcm/pcm_dmix.c
--- a/src/pcm/pcm_dmix.c	Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dmix.c	Wed Nov 21 12:06:52 2007 +0100
@@ -420,7 +420,14 @@ static int snd_pcm_dmix_status(snd_pcm_t
 	memset(status, 0, sizeof(*status));
 	status->state = snd_pcm_dmix_state(pcm);
 	status->trigger_tstamp = dmix->trigger_tstamp;
-	status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
+	if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+		status->tstamp = snd_pcm_hw_fast_tstamp(dmix->spcm);
+	else {
+		struct timeval tv;
+		gettimeofday(&tv, 0);
+		status->tstamp.tv_sec = tv.tv_sec;
+		status->tstamp.tv_nsec = tv.tv_usec * 1000L;
+	}
 	status->avail = snd_pcm_mmap_playback_avail(pcm);
 	status->avail_max = status->avail > dmix->avail_max ? status->avail : dmix->avail_max;
 	dmix->avail_max = 0;
diff -r 39d34d6a4587 src/pcm/pcm_dshare.c
--- a/src/pcm/pcm_dshare.c	Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dshare.c	Wed Nov 21 12:06:52 2007 +0100
@@ -229,7 +229,14 @@ static int snd_pcm_dshare_status(snd_pcm
 	memset(status, 0, sizeof(*status));
 	status->state = snd_pcm_state(dshare->spcm);
 	status->trigger_tstamp = dshare->trigger_tstamp;
-	status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
+	if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+		status->tstamp = snd_pcm_hw_fast_tstamp(dshare->spcm);
+	else {
+		struct timeval tv;
+		gettimeofday(&tv, 0);
+		status->tstamp.tv_sec = tv.tv_sec;
+		status->tstamp.tv_nsec = tv.tv_usec * 1000L;
+	}
 	status->avail = snd_pcm_mmap_playback_avail(pcm);
 	status->avail_max = status->avail > dshare->avail_max ? status->avail : dshare->avail_max;
 	dshare->avail_max = 0;
diff -r 39d34d6a4587 src/pcm/pcm_dsnoop.c
--- a/src/pcm/pcm_dsnoop.c	Tue Nov 20 15:29:10 2007 +0100
+++ b/src/pcm/pcm_dsnoop.c	Wed Nov 21 12:06:52 2007 +0100
@@ -175,7 +175,14 @@ static int snd_pcm_dsnoop_status(snd_pcm
 	state = snd_pcm_state(dsnoop->spcm);
 	status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
 	status->trigger_tstamp = dsnoop->trigger_tstamp;
-	status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
+	if (pcm->tstamp_mode == SND_PCM_TSTAMP_MMAP)
+		status->tstamp = snd_pcm_hw_fast_tstamp(dsnoop->spcm);
+	else {
+		struct timeval tv;
+		gettimeofday(&tv, 0);
+		status->tstamp.tv_sec = tv.tv_sec;
+		status->tstamp.tv_nsec = tv.tv_usec * 1000L;
+	}
 	status->avail = snd_pcm_mmap_capture_avail(pcm);
 	status->avail_max = status->avail > dsnoop->avail_max ? status->avail : dsnoop->avail_max;
 	dsnoop->avail_max = 0;


More information about the Alsa-devel mailing list