On Wed, Apr 01, 2020 at 05:59:52PM +0200, Takashi Iwai wrote: > Heh, my initial patch was also with that strong type, but I changed it > because I wanted to allow the "system default" value, which isn't > represented with that type. I stand corrected. I noticed that after sending my email :( The patch actually did not install the tstamp configuration option. I did add the installation of the option all direct based plugins (dmix/dsnoop/dshare), that with a global configuration option. I did some testing and quickly found out some defaults for sw_params are installed in pcm_params.c:_snd_pcm_hw_params_internal from a snd_pcm_hw_params installation call. Those defaults are defined in pcm_params.c:snd_pcm_sw_params_default which tstamp value will break in the case of a plugin pipeline ending with already running direct plugin. It means that all calls to snd_pcm_sw_params done internally should have their sw_params values investigated to see if they work with a plugin pipeline ending with an already running direct plugin. For the first case, in pcm_params.c:_snd_pcm_hw_params_internal, it seems that "valid" default sw_params for a plugin pipeline should be made sort of recursive or "something else". I'll start to try to find a way to deal with with this first case and will start to investigate those internal sw_params uses. Meanwhile, below is the modified patch. cheers, -- Sylvain --- diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf index a091b810..0e01c887 100644 --- a/src/conf/alsa.conf +++ b/src/conf/alsa.conf @@ -69,6 +69,7 @@ defaults.pcm.minperiodtime 5000 # in us defaults.pcm.ipc_key 5678293 defaults.pcm.ipc_gid audio defaults.pcm.ipc_perm 0660 +defaults.pcm.tstamp_type "default" defaults.pcm.dmix.max_periods 0 defaults.pcm.dmix.channels 2 defaults.pcm.dmix.rate 48000 diff --git a/src/conf/pcm/dmix.conf b/src/conf/pcm/dmix.conf index 7fa5c8b2..50e573da 100644 --- a/src/conf/pcm/dmix.conf +++ b/src/conf/pcm/dmix.conf @@ -56,6 +56,10 @@ pcm.!dmix { @func refer name defaults.pcm.ipc_perm } + tstamp_type { + @func refer + name defaults.pcm.tstamp_type + } slave { pcm { type hw diff --git a/src/conf/pcm/dsnoop.conf b/src/conf/pcm/dsnoop.conf index abbd44f7..f4336e5f 100644 --- a/src/conf/pcm/dsnoop.conf +++ b/src/conf/pcm/dsnoop.conf @@ -49,6 +49,10 @@ pcm.!dsnoop { @func refer name defaults.pcm.ipc_perm } + tstamp_type { + @func refer + name defaults.pcm.tstamp_type + } slave { pcm { type hw diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c index 54d99005..b6f5c731 100644 --- a/src/pcm/pcm_direct.c +++ b/src/pcm/pcm_direct.c @@ -991,8 +991,13 @@ int snd_pcm_direct_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) return 0; } -int snd_pcm_direct_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED) +int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) { + snd_pcm_direct_t *dmix = pcm->private_data; + + if ((int)params->tstamp_type != dmix->tstamp_type) + return -EINVAL; + /* values are cached in the pcm structure */ return 0; } @@ -1318,6 +1323,15 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str return ret; } + if (dmix->tstamp_type != -1) { + ret = snd_pcm_sw_params_set_tstamp_type(spcm, &sw_params, + dmix->tstamp_type); + if (ret < 0) { + SNDERR("unable to set tstamp type"); + return ret; + } + } + if (dmix->type != SND_PCM_TYPE_DMIX && dmix->type != SND_PCM_TYPE_DSHARE) goto __skip_silencing; @@ -1341,6 +1355,9 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str return ret; } + /* copy back the slave setup */ + dmix->tstamp_type = (int)sw_params.tstamp_type; + if (dmix->type == SND_PCM_TYPE_DSHARE) { const snd_pcm_channel_area_t *dst_areas; dst_areas = snd_pcm_mmap_areas(spcm); @@ -1878,6 +1895,7 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, rec->var_periodsize = 0; rec->direct_memory_access = 1; rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO; + rec->tstamp_type = -1; /* read defaults */ if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) { @@ -1941,6 +1959,27 @@ int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, continue; } + if (strcmp(id, "tstamp_type") == 0) { + const char *str; + err = snd_config_get_string(n, &str); + if (err < 0) { + SNDERR("Invalid type for %s", id); + return -EINVAL; + } + if (strcmp(str, "default") == 0) + rec->tstamp_type = -1; + else if (strcmp(str, "gettimeofday") == 0) + rec->tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; + else if (strcmp(str, "monotonic") == 0) + rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC; + else if (strcmp(str, "monotonic_raw") == 0) + rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW; + else { + SNDERR("The field tstamp_type is invalid : %s", str); + return -EINVAL; + } + continue; + } if (strcmp(id, "ipc_gid") == 0) { char *group; char *endp; diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h index 221edbe1..63dd645b 100644 --- a/src/pcm/pcm_direct.h +++ b/src/pcm/pcm_direct.h @@ -173,6 +173,7 @@ struct snd_pcm_direct { unsigned int recoveries; /* mirror of executed recoveries on slave */ int direct_memory_access; /* use arch-optimized buffer RW */ snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment; + int tstamp_type; union { struct { int shmid_sum; /* IPC global sum ring buffer memory identification */ @@ -357,6 +358,7 @@ struct snd_pcm_direct_open_conf { int var_periodsize; int direct_memory_access; snd_pcm_direct_hw_ptr_alignment_t hw_ptr_alignment; + int tstamp_type; snd_config_t *slave; snd_config_t *bindings; }; diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index d533f40c..843fa316 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -1038,6 +1038,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, dmix->ipc_key = opts->ipc_key; dmix->ipc_perm = opts->ipc_perm; dmix->ipc_gid = opts->ipc_gid; + dmix->tstamp_type = opts->tstamp_type; dmix->semid = -1; dmix->shmid = -1; @@ -1237,6 +1238,9 @@ pcm.name { # roundup # rounddown # auto (default) + tstamp_type STR # timestamp type + # STR can be one of the below strings : + # default, gettimeofday, monotonic, monotonic_raw slave STR # or slave { # Slave definition diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 59448cfb..6a99452b 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -723,6 +723,7 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, dshare->ipc_key = opts->ipc_key; dshare->ipc_perm = opts->ipc_perm; dshare->ipc_gid = opts->ipc_gid; + dshare->tstamp_type = opts->tstamp_type; dshare->semid = -1; dshare->shmid = -1; @@ -929,6 +930,9 @@ pcm.name { # roundup # rounddown # auto (default) + tstamp_type STR # timestamp type + # STR can be one of the below strings : + # default, gettimeofday, monotonic, monotonic_raw slave STR # or slave { # Slave definition diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index 24f472c7..c64df381 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -591,6 +591,7 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, dsnoop->ipc_key = opts->ipc_key; dsnoop->ipc_perm = opts->ipc_perm; dsnoop->ipc_gid = opts->ipc_gid; + dsnoop->tstamp_type = opts->tstamp_type; dsnoop->semid = -1; dsnoop->shmid = -1; @@ -780,6 +781,9 @@ pcm.name { # roundup # rounddown # auto (default) + tstamp_type STR # timestamp type + # STR can be one of the below strings : + # default, gettimeofday, monotonic, monotonic_raw slave STR # or slave { # Slave definition diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 05ed935f..89d4125b 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -928,6 +928,8 @@ int INTERNAL(snd_pcm_hw_params_set_buffer_size_last)(snd_pcm_t *pcm, snd_pcm_hw_ int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_t val); int INTERNAL(snd_pcm_sw_params_get_tstamp_mode)(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_t *val); +int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t val); +int snd_pcm_sw_params_get_tstamp_type(const snd_pcm_sw_params_t *params, snd_pcm_tstamp_type_t *val); int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); int INTERNAL(snd_pcm_sw_params_get_avail_min)(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val); int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);