[alsa-devel] [PATCH 1/2] ALSA: core: add hooks for audio timestamps read from WALLCLOCK

Takashi Iwai tiwai at suse.de
Thu Jun 14 09:27:32 CEST 2012


At Wed, 13 Jun 2012 15:26:31 -0500,
Pierre-Louis Bossart wrote:
> 
> Add new .audio_wallclock routine to enable fine-grain synchronization
> between monotonic system time and audio hardware time.
> Prior to this patch, the clock drift estimation was handled in
> user-space by comparing frames and system time.
> Using the wallclock, if supported in hardware, allows for a
> much better sub-microsecond precision and a common drift tracking for
> all devices sharing the same wall clock (master clock).
> 
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> ---
>  include/sound/asound.h  |    7 ++++++-
>  include/sound/pcm.h     |    2 ++
>  sound/core/pcm_lib.c    |   15 +++++++++++++--
>  sound/core/pcm_native.c |    2 ++
>  4 files changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/include/sound/asound.h b/include/sound/asound.h
> index 0876a1e..7c768fa 100644
> --- a/include/sound/asound.h
> +++ b/include/sound/asound.h
> @@ -274,6 +274,7 @@ typedef int __bitwise snd_pcm_subformat_t;
>  #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
>  #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
>  #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP	0x00800000	/* period wakeup can be disabled */
> +#define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
>  #define SNDRV_PCM_INFO_FIFO_IN_FRAMES	0x80000000	/* internal kernel flag - FIFO size is in frames */
>  
>  typedef int __bitwise snd_pcm_state_t;
> @@ -422,7 +423,10 @@ struct snd_pcm_status {
>  	snd_pcm_uframes_t avail_max;	/* max frames available on hw since last status */
>  	snd_pcm_uframes_t overrange;	/* count of ADC (capture) overrange detections from last status */
>  	snd_pcm_state_t suspended_state; /* suspended stream state */
> -	unsigned char reserved[60];	/* must be filled with zero */
> +	union {
> +		unsigned char reserved[60];	/* must be filled with zero */
> +		struct timespec audio_tstamp;	/* audio wall clock timestamp */
> +	} ext;

The biggest problem of struct timespec is that it's pretty much
arch-dependent.  But since it's used in all other places, we need to
live with that...

Usually when we add a new field, we don't use union.  Just decrease
sizeof(struct timespec) from reserved[] size.

No matter whether using union or not, it doesn't mean that the whole
struct size work is kept.  The field might be aligned since we haven't
added the packed attribute.  Maybe better to add a padding to align
64bit before audio_tstamp, then cross your finger.

>  };
>  
>  struct snd_pcm_mmap_status {
> @@ -430,6 +434,7 @@ struct snd_pcm_mmap_status {
>  	int pad1;			/* Needed for 64 bit alignment */
>  	snd_pcm_uframes_t hw_ptr;	/* RO: hw ptr (0...boundary-1) */
>  	struct timespec tstamp;		/* Timestamp */
> +	struct timespec audio_tstamp;	/* audio wall clock timestamp */
>  	snd_pcm_state_t suspended_state; /* RO: suspended stream state */
>  };

struct snd_pcm_mmap_status is mmapped to user-space, thus it must be
backward compatible.  Always append the new field.

In addition, if you change the ABI, please change the PCM protocol
version, so that alsa-lib can detect the ABI change.

Also, last not but least, don't forget to convert pcm_compat.c.

Other than these, changes look good to me.


thanks,

Takashi

> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index 0d11128..75d9db0 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -71,6 +71,8 @@ struct snd_pcm_ops {
>  	int (*prepare)(struct snd_pcm_substream *substream);
>  	int (*trigger)(struct snd_pcm_substream *substream, int cmd);
>  	snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
> +	int (*wall_clock)(struct snd_pcm_substream *substream,
> +			  struct timespec *audio_ts);
>  	int (*copy)(struct snd_pcm_substream *substream, int channel,
>  		    snd_pcm_uframes_t pos,
>  		    void __user *buf, snd_pcm_uframes_t count);
> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
> index 8f312fa..beece7d 100644
> --- a/sound/core/pcm_lib.c
> +++ b/sound/core/pcm_lib.c
> @@ -315,6 +315,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
>  	unsigned long jdelta;
>  	unsigned long curr_jiffies;
>  	struct timespec curr_tstamp;
> +	struct timespec audio_tstamp;
>  
>  	old_hw_ptr = runtime->status->hw_ptr;
>  
> @@ -326,9 +327,17 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
>  	 */
>  	pos = substream->ops->pointer(substream);
>  	curr_jiffies = jiffies;
> -	if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
> +	if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
>  		snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
>  
> +		if ((runtime->hw.info & SNDRV_PCM_INFO_HAS_WALL_CLOCK) &&
> +			(substream->ops->wall_clock))
> +			substream->ops->wall_clock(substream, &audio_tstamp);
> +		else
> +			/* no audio tstamp available, initialize anyway */
> +			audio_tstamp = curr_tstamp;
> +	}
> +
>  	if (pos == SNDRV_PCM_POS_XRUN) {
>  		xrun(substream);
>  		return -EPIPE;
> @@ -506,8 +515,10 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
>  	runtime->hw_ptr_base = hw_base;
>  	runtime->status->hw_ptr = new_hw_ptr;
>  	runtime->hw_ptr_jiffies = curr_jiffies;
> -	if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
> +	if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
>  		runtime->status->tstamp = curr_tstamp;
> +		runtime->status->audio_tstamp = audio_tstamp;
> +	}
>  
>  	return snd_pcm_update_state(substream, runtime);
>  }
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 53b5ada..bf0176b 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -594,6 +594,8 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
>  		snd_pcm_update_hw_ptr(substream);
>  		if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
>  			status->tstamp = runtime->status->tstamp;
> +			status->ext.audio_tstamp =
> +				runtime->status->audio_tstamp;
>  			goto _tstamp_end;
>  		}
>  	}
> -- 
> 1.7.6.5
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 


More information about the Alsa-devel mailing list