alsa: Added handle for controlling htimestamp autodisable

You can now do this to permanently enable htimestamp:

pw-cli s 38 Props '{ params: [ api.alsa.htimestamp.max-errors: 0, api.alsa.htimestamp: true ]}'
This commit is contained in:
Dimitrios Katsaros 2024-02-20 08:47:03 +01:00
parent 2e29177964
commit 539fdc5477
3 changed files with 22 additions and 3 deletions

View File

@ -261,6 +261,10 @@ Use ALSA htimestamps in scheduling, instead of the system clock.
Some ALSA drivers produce bad timestamps, so this is not enabled by default
and will be disabled at runtime if it looks like the ALSA timestamps are bad.
@PAR@ device-param api.alsa.htimestamp.max-errors
Specify the number of consecutive errors before htimestamp is disabled.
Setting this to 0 makes htimestamp never get disabled.
@PAR@ device-param api.alsa.disable-tsched = false
Disable timer-based scheduling, and use IRQ for scheduling instead.
The "Pro Audio" profile will usually enable this setting, if it is expected it works on the hardware.

View File

@ -133,6 +133,8 @@ static int alsa_set_param(struct state *state, const char *k, const char *s)
state->multi_rate = spa_atob(s);
} else if (spa_streq(k, "api.alsa.htimestamp")) {
state->htimestamp = spa_atob(s);
} else if (spa_streq(k, "api.alsa.htimestamp.max-errors")) {
state->htimestamp_max_errors = atoi(s);
} else if (spa_streq(k, "api.alsa.auto-link")) {
state->auto_link = spa_atob(s);
} else if (spa_streq(k, "latency.internal.rate")) {
@ -411,9 +413,17 @@ struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
SPA_PROP_INFO_type, SPA_POD_String(state->clock_name),
SPA_PROP_INFO_params, SPA_POD_Bool(true));
break;
case 18:
param = spa_pod_builder_add_object(b,
SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
SPA_PROP_INFO_name, SPA_POD_String("api.alsa.htimestamp.max-errors"),
SPA_PROP_INFO_description, SPA_POD_String("Max errors before disabling htimestamp"),
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(state->htimestamp_max_errors, 0, INT32_MAX),
SPA_PROP_INFO_params, SPA_POD_Bool(true));
break;
// While adding params here, update the math in default too
default:
idx -= 17;
idx -= 18;
if (idx <= state->num_bind_ctls)
param = enum_bind_ctl_propinfo(state, idx - 1, b);
else
@ -530,6 +540,9 @@ int spa_alsa_add_prop_params(struct state *state, struct spa_pod_builder *b)
spa_pod_builder_string(b, "api.alsa.htimestamp");
spa_pod_builder_bool(b, state->htimestamp);
spa_pod_builder_string(b, "api.alsa.htimestamp.max-errors");
spa_pod_builder_int(b, state->htimestamp_max_errors);
spa_pod_builder_string(b, "latency.internal.rate");
spa_pod_builder_int(b, state->process_latency.rate);
@ -753,6 +766,7 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info)
state->multi_rate = true;
state->htimestamp = false;
state->htimestamp_max_errors = MAX_HTIMESTAMP_ERROR;
for (i = 0; info && i < info->n_items; i++) {
const char *k = info->items[i].key;
const char *s = info->items[i].value;
@ -2490,8 +2504,8 @@ static int get_avail(struct state *state, uint64_t current_time, snd_pcm_uframes
if (SPA_ABS(diff) < state->threshold * 3) {
*delay += SPA_CLAMP(diff, -((int64_t)state->threshold), (int64_t)state->threshold);
state->htimestamp_error = 0;
} else {
if (++state->htimestamp_error > MAX_HTIMESTAMP_ERROR) {
} else if (state->htimestamp_max_errors) {
if (++state->htimestamp_error > state->htimestamp_max_errors) {
spa_log_error(state->log, "%s: wrong htimestamps from driver, disabling",
state->name);
state->htimestamp_error = 0;

View File

@ -203,6 +203,7 @@ struct state {
uint32_t min_delay;
uint32_t max_delay;
uint32_t htimestamp_error;
uint32_t htimestamp_max_errors;
struct spa_fraction driver_rate;
uint32_t driver_duration;