[alsa-devel] Retrieving original timestamps in dsnoop.

Pontus Oldberg pontus.oldberg at axis.com
Fri Oct 29 11:58:55 CEST 2010


Hello,
I am working in a gstreamer based project where we are using alsasrc to feed the audio pipeline. On of the things that we need to be able to do is to get the monotonic timestamp from the alsalib in order for our video and audio to be perfectly synchronized. This worked fine until we introduced the dsnoop plug-in which creates its own timestamp reference. I have played around with the dsnoop plugin and created a preliminary fix that gives us the result that we want.

I'd like to know if this looks like the way to go or if this can be obtained in any other way. We are using dsnoop in order to be able to create two separate audio pipelines, we don't care about stereo, just simple mono streams.  

? libs/alsa-lib/build
? libs/alsa-lib/alsa-lib/autom4te.cache
? libs/alsa-lib/alsa-lib/src/control/ctl_symbols_list.c
? libs/alsa-lib/alsa-lib/src/pcm/pcm_symbols_list.c
Index: libs/alsa-lib/alsa-lib/src/pcm/pcm_direct.h
===================================================================
RCS file: /usr/local/cvs/linux/libs/alsa-lib/alsa-lib/src/pcm/pcm_direct.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 pcm_direct.h
--- libs/alsa-lib/alsa-lib/src/pcm/pcm_direct.h	6 Sep 2010 08:18:20 -0000	1.1.1.2
+++ libs/alsa-lib/alsa-lib/src/pcm/pcm_direct.h	29 Oct 2010 09:56:08 -0000
@@ -114,6 +114,14 @@
 	} u;
 } snd_pcm_direct_share_t;
 
+/*
+ * Defines the clock type to use
+ */
+enum snd_pcm_sub_clock_type {
+  SND_PCM_SLAVE_CLOCK_DEFAULT = 0x00,
+  SND_PCM_SLAVE_CLOCK_SUB =0x01,
+};
+
 typedef struct snd_pcm_direct snd_pcm_direct_t;
 
 struct snd_pcm_direct {
@@ -153,6 +161,7 @@
 	int max_periods;		/* max periods (-1 = fixed periods, 0 = max buffer size) */
 	unsigned int channels;		/* client's channels */
 	unsigned int *bindings;
+	int sub_clock;
 	union {
 		struct {
 			int shmid_sum;			/* IPC global sum ring buffer memory identification */
Index: libs/alsa-lib/alsa-lib/src/pcm/pcm_dsnoop.c
===================================================================
RCS file: /usr/local/cvs/linux/libs/alsa-lib/alsa-lib/src/pcm/pcm_dsnoop.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 pcm_dsnoop.c
--- libs/alsa-lib/alsa-lib/src/pcm/pcm_dsnoop.c	6 Sep 2010 08:18:20 -0000	1.1.1.2
+++ libs/alsa-lib/alsa-lib/src/pcm/pcm_dsnoop.c	29 Oct 2010 09:56:08 -0000
@@ -51,7 +51,7 @@
 #endif
 
 /*
- *
+ * Handles packing and formating of buffers
  */
 
 static void snoop_areas(snd_pcm_direct_t *dsnoop,
@@ -168,11 +168,18 @@
 	default:
 		break;
 	}
-	memset(status, 0, sizeof(*status));
+
+	memset(status, 0, sizeof(status));
 	state = snd_pcm_state(dsnoop->spcm);
 	status->state = state == SND_PCM_STATE_RUNNING ? dsnoop->state : state;
-	status->trigger_tstamp = dsnoop->trigger_tstamp;
-	gettimestamp(&status->tstamp, pcm->monotonic);
+
+	if (dsnoop->sub_clock == SND_PCM_SLAVE_CLOCK_SUB) {
+		snd_pcm_status(dsnoop->spcm, status);
+	} else {
+		status->trigger_tstamp = dsnoop->trigger_tstamp;
+		gettimestamp(&status->tstamp, pcm->monotonic);
+	}
+
 	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;
@@ -197,18 +204,21 @@
 static int snd_pcm_dsnoop_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
 	snd_pcm_direct_t *dsnoop = pcm->private_data;
-	int err;
+	int err = 0;
 	
 	switch(dsnoop->state) {
 	case SNDRV_PCM_STATE_DRAINING:
 	case SNDRV_PCM_STATE_RUNNING:
-		err = snd_pcm_dsnoop_sync_ptr(pcm);
+	  err = snd_pcm_dsnoop_sync_ptr(pcm);
 		if (err < 0)
 			return err;
 	case SNDRV_PCM_STATE_PREPARED:
 	case SNDRV_PCM_STATE_SUSPENDED:
-		*delayp = snd_pcm_mmap_capture_hw_avail(pcm);
-		return 0;
+		if (dsnoop->sub_clock == SND_PCM_SLAVE_CLOCK_SUB)
+			err = dsnoop->spcm->fast_ops->delay(dsnoop->spcm, delayp);
+		else
+			*delayp = snd_pcm_mmap_capture_hw_avail(pcm);
+		return err;
 	case SNDRV_PCM_STATE_XRUN:
 		return -EPIPE;
 	case SNDRV_PCM_STATE_DISCONNECTED:
@@ -271,7 +281,12 @@
 	if (err < 0)
 		return err;
 	dsnoop->state = SND_PCM_STATE_RUNNING;
-	gettimestamp(&dsnoop->trigger_tstamp, pcm->monotonic);
+	if (dsnoop->sub_clock == SND_PCM_SLAVE_CLOCK_SUB) {
+		snd_pcm_status_t status;
+		snd_pcm_status(dsnoop->spcm, &status);
+		dsnoop->trigger_tstamp = status.trigger_tstamp;
+	} else
+		gettimestamp(&dsnoop->trigger_tstamp, pcm->monotonic);
 	return 0;
 }
 
@@ -421,6 +436,7 @@
 	return snd_pcm_mmap_capture_avail(pcm);
 }
 
+/* TODO: This function is faulty, needs fixing */
 static int snd_pcm_dsnoop_htimestamp(snd_pcm_t *pcm,
 				     snd_pcm_uframes_t *avail,
 				     snd_htimestamp_t *tstamp)
@@ -673,6 +689,9 @@
 	if (dsnoop->channels == UINT_MAX)
 		dsnoop->channels = dsnoop->shmptr->s.channels;
 	
+	/* TODO: Needs to be loaded from the config file */	
+	dsnoop->sub_clock = SND_PCM_SLAVE_CLOCK_SUB;
+
 	snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
 
 	*pcmp = pcm;

/Regards
/Pontus


More information about the Alsa-devel mailing list