alsa: rework batch handling a bit

By default, use a 512 period for batch and use 512 headroom
Add a property to disable special batch handling.
This commit is contained in:
Wim Taymans 2021-01-21 17:10:48 +01:00
parent af092a9a7e
commit 73896bfa83
5 changed files with 28 additions and 31 deletions

View file

@ -776,6 +776,7 @@ impl_init(const struct spa_handle_factory *factory,
snd_config_update_free_global(); snd_config_update_free_global();
for (i = 0; info && i < info->n_items; i++) { for (i = 0; info && i < info->n_items; i++) {
const char *s = info->items[i].value;
if (!strcmp(info->items[i].key, SPA_KEY_API_ALSA_PATH)) { if (!strcmp(info->items[i].key, SPA_KEY_API_ALSA_PATH)) {
snprintf(this->props.device, 63, "%s", info->items[i].value); snprintf(this->props.device, 63, "%s", info->items[i].value);
} else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_CHANNELS)) { } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_CHANNELS)) {
@ -786,20 +787,21 @@ impl_init(const struct spa_handle_factory *factory,
this->default_format = spa_alsa_format_from_name(info->items[i].value, 128); this->default_format = spa_alsa_format_from_name(info->items[i].value, 128);
} else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) { } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) {
size_t len; size_t len;
const char *p = info->items[i].value; while (*s && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) {
while (*p && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) { if ((len = strcspn(s, ",")) == 0)
if ((len = strcspn(p, ",")) == 0)
break; break;
this->default_pos.pos[this->default_pos.channels++] = this->default_pos.pos[this->default_pos.channels++] =
spa_alsa_channel_from_name(p, len); spa_alsa_channel_from_name(s, len);
p += len + strspn(p+len, ","); s += len + strspn(s+len, ",");
} }
} else if (!strcmp(info->items[i].key, "api.alsa.period-size")) { } else if (!strcmp(info->items[i].key, "api.alsa.period-size")) {
this->default_period_size = atoi(info->items[i].value); this->default_period_size = atoi(info->items[i].value);
} else if (!strcmp(info->items[i].key, "api.alsa.headroom")) { } else if (!strcmp(info->items[i].key, "api.alsa.headroom")) {
this->default_headroom = atoi(info->items[i].value); this->default_headroom = atoi(info->items[i].value);
} else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) { } else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) {
this->disable_mmap = atoi(info->items[i].value); this->disable_mmap = (strcmp(s, "true") == 0 || atoi(s) == 1);
} else if (!strcmp(info->items[i].key, "api.alsa.disable-batch")) {
this->disable_batch = (strcmp(s, "true") == 0 || atoi(s) == 1);
} }
} }
return 0; return 0;

View file

@ -797,6 +797,7 @@ impl_init(const struct spa_handle_factory *factory,
snd_config_update_free_global(); snd_config_update_free_global();
for (i = 0; info && i < info->n_items; i++) { for (i = 0; info && i < info->n_items; i++) {
const char *s = info->items[i].value;
if (!strcmp(info->items[i].key, SPA_KEY_API_ALSA_PATH)) { if (!strcmp(info->items[i].key, SPA_KEY_API_ALSA_PATH)) {
snprintf(this->props.device, 63, "%s", info->items[i].value); snprintf(this->props.device, 63, "%s", info->items[i].value);
} else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_CHANNELS)) { } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_CHANNELS)) {
@ -807,20 +808,21 @@ impl_init(const struct spa_handle_factory *factory,
this->default_format = spa_alsa_format_from_name(info->items[i].value, 128); this->default_format = spa_alsa_format_from_name(info->items[i].value, 128);
} else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) { } else if (!strcmp(info->items[i].key, SPA_KEY_AUDIO_POSITION)) {
size_t len; size_t len;
const char *p = info->items[i].value; while (*s && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) {
while (*p && this->default_pos.channels < SPA_AUDIO_MAX_CHANNELS) { if ((len = strcspn(s, ",")) == 0)
if ((len = strcspn(p, ",")) == 0)
break; break;
this->default_pos.pos[this->default_pos.channels++] = this->default_pos.pos[this->default_pos.channels++] =
spa_alsa_channel_from_name(p, len); spa_alsa_channel_from_name(s, len);
p += len + strspn(p+len, ","); s += len + strspn(s+len, ",");
} }
} else if (!strcmp(info->items[i].key, "api.alsa.period-size")) { } else if (!strcmp(info->items[i].key, "api.alsa.period-size")) {
this->default_period_size = atoi(info->items[i].value); this->default_period_size = atoi(info->items[i].value);
} else if (!strcmp(info->items[i].key, "api.alsa.headroom")) { } else if (!strcmp(info->items[i].key, "api.alsa.headroom")) {
this->default_headroom = atoi(info->items[i].value); this->default_headroom = atoi(info->items[i].value);
} else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) { } else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) {
this->disable_mmap = atoi(info->items[i].value); this->disable_mmap = (strcmp(s, "true") == 0 || atoi(s) == 1);
} else if (!strcmp(info->items[i].key, "api.alsa.disable-batch")) {
this->disable_batch = (strcmp(s, "true") == 0 || atoi(s) == 1);
} }
} }
return 0; return 0;

View file

@ -584,18 +584,9 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
dir = 0; dir = 0;
period_size = state->default_period_size ? state->default_period_size : 1024; period_size = state->default_period_size ? state->default_period_size : 1024;
is_batch = snd_pcm_hw_params_is_batch(params); is_batch = snd_pcm_hw_params_is_batch(params) &&
if (is_batch) { !state->disable_batch;
const char *id;
snd_pcm_info_t* pcm_info;
snd_pcm_info_alloca(&pcm_info);
if (snd_pcm_info(hndl, pcm_info) == 0 &&
(id = snd_pcm_info_get_id(pcm_info)) != NULL) {
/* usb devices have low enough transfer size */
if (strcmp(id, "USB Audio") == 0)
is_batch = false;
}
}
if (is_batch) { if (is_batch) {
/* batch devices get their hw pointers updated every period. Make /* batch devices get their hw pointers updated every period. Make
* the period smaller and add one period of headroom */ * the period smaller and add one period of headroom */
@ -608,23 +599,23 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
CHECK(snd_pcm_hw_params_get_buffer_size_max(params, &state->buffer_frames), "get_buffer_size_max"); CHECK(snd_pcm_hw_params_get_buffer_size_max(params, &state->buffer_frames), "get_buffer_size_max");
CHECK(snd_pcm_hw_params_set_buffer_size_near(hndl, params, &state->buffer_frames), "set_buffer_size_near"); CHECK(snd_pcm_hw_params_set_buffer_size_near(hndl, params, &state->buffer_frames), "set_buffer_size_near");
if (state->default_headroom == 0)
state->headroom = is_batch ? period_size : 0;
else
state->headroom = state->default_headroom; state->headroom = state->default_headroom;
if (is_batch)
state->headroom += period_size;
state->period_frames = period_size; state->period_frames = period_size;
periods = state->buffer_frames / state->period_frames; periods = state->buffer_frames / state->period_frames;
spa_log_info(state->log, NAME" %s (%s): format:%s access:%s-%s rate:%d channels:%d " spa_log_info(state->log, NAME" %s (%s): format:%s access:%s-%s rate:%d channels:%d "
"buffer frames %lu, period frames %lu, periods %u, frame_size %zd", "buffer frames %lu, period frames %lu, periods %u, frame_size %zd"
"headroom %u",
state->props.device, state->props.device,
state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback", state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback",
snd_pcm_format_name(state->format), snd_pcm_format_name(state->format),
state->use_mmap ? "mmap" : "rw", state->use_mmap ? "mmap" : "rw",
planar ? "planar" : "interleaved", planar ? "planar" : "interleaved",
state->rate, state->channels, state->buffer_frames, state->period_frames, state->rate, state->channels, state->buffer_frames, state->period_frames,
periods, state->frame_size); periods, state->frame_size, state->headroom);
/* write the parameters to device */ /* write the parameters to device */
CHECK(snd_pcm_hw_params(hndl, params), "set_hw_params"); CHECK(snd_pcm_hw_params(hndl, params), "set_hw_params");

View file

@ -117,6 +117,7 @@ struct state {
unsigned int default_rate; unsigned int default_rate;
struct channel_map default_pos; struct channel_map default_pos;
unsigned int disable_mmap; unsigned int disable_mmap;
unsigned int disable_batch;
snd_pcm_uframes_t buffer_frames; snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames; snd_pcm_uframes_t period_frames;

View file

@ -58,6 +58,7 @@ rules = [
#api.alsa.period-size = 1024 #api.alsa.period-size = 1024
#api.alsa.headroom = 0 #api.alsa.headroom = 0
#api.alsa.disable-mmap = false #api.alsa.disable-mmap = false
#api.alsa.disable-batch = false
} }
} }
} }