From 5383782336fa08b9c6da7f2c6981db3721b94e65 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 23 Oct 2019 16:04:03 +0200 Subject: [PATCH] alsa: Disable rate matching for the same card Add a clock name to the clock, remove the old api/clock_id. This makes it easier to add descriptive names Place the alsa card number in the clock name. Check the clock name of the master clock and if it matches our own clock, disable rate matching. --- spa/include/spa/node/io.h | 5 +++-- spa/plugins/alsa/alsa-pcm-source.c | 2 ++ spa/plugins/alsa/alsa-pcm.c | 28 ++++++++++++++++++++++++---- spa/plugins/alsa/alsa-pcm.h | 2 ++ spa/tests/test-node.c | 4 ++-- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/spa/include/spa/node/io.h b/spa/include/spa/node/io.h index bb8434a77..49d7e8af0 100644 --- a/spa/include/spa/node/io.h +++ b/spa/include/spa/node/io.h @@ -123,8 +123,9 @@ struct spa_io_range { struct spa_io_clock { uint32_t flags; /**< clock flags */ uint32_t id; /**< unique clock id, set by application */ - uint32_t api; /**< api of the clock */ - uint32_t clock_id; /**< api specific clock id */ + char name[64]; /**< clock name prefixed with API, set by node. The clock name + * is unique per clock and can be used to check if nodes + * share the same clock. */ uint64_t nsec; /**< time in nanoseconds against monotonic clock */ uint64_t count; /**< a media specific counter. Can be used to detect * gaps in the media. It usually represents the amount diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index 146868cc9..07726b114 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -177,6 +177,8 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size) switch (id) { case SPA_IO_Clock: + if (size > 0 && size < sizeof(struct spa_io_clock)) + return -EINVAL; this->clock = data; break; case SPA_IO_Position: diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index ce75cc48d..ca37028b5 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -21,6 +21,7 @@ static int spa_alsa_open(struct state *state) { int err; struct props *props = &state->props; + snd_pcm_info_t *pcminfo; if (state->opened) return 0; @@ -42,6 +43,16 @@ static int spa_alsa_open(struct state *state) state->timerfd = err; + snd_pcm_info_alloca(&pcminfo); + snd_pcm_info(state->hndl, pcminfo); + + /* we would love to use the sync_id but it always returns 0, so use the + * card id for now */ + state->card = snd_pcm_info_get_card(pcminfo); + if (state->clock) { + snprintf(state->clock->name, sizeof(state->clock->name), + "api.alsa.%d", state->card); + } state->opened = true; state->sample_count = 0; state->sample_time = 0; @@ -608,7 +619,7 @@ static int get_status(struct state *state, snd_pcm_uframes_t *delay, snd_pcm_ufr *target = state->last_threshold; - if (state->slaved && state->rate_match) { + if (state->matching && state->rate_match) { state->delay = state->rate_match->delay; state->read_size = state->rate_match->size; /* We try to compensate for the latency introduced by rate matching @@ -618,6 +629,8 @@ static int get_status(struct state *state, snd_pcm_uframes_t *delay, snd_pcm_ufr if (*target <= state->delay + 48) state->delay = SPA_MAX(0, (int)(*target - 48 - state->delay)); *target -= state->delay; + } else { + state->delay = state->read_size = 0; } if (state->stream == SND_PCM_STREAM_PLAYBACK) { @@ -678,7 +691,7 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del else state->rate_match->rate = SPA_CLAMP(1.0/corr, 0.95, 1.05); - SPA_FLAG_UPDATE(state->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE, slave); + SPA_FLAG_UPDATE(state->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE, state->matching); } state->next_time += state->threshold / corr * 1e9 / state->rate; @@ -1137,8 +1150,14 @@ int spa_alsa_start(struct state *state) return 0; state->slaved = is_slaved(state); + state->matching = state->slaved; if (state->position) { + int card; + if (sscanf(state->position->clock.name, "api.alsa.%d", &card) == 1 && + card == state->card) { + state->matching = false; + } state->duration = state->position->clock.duration; state->rate_denom = state->position->clock.rate.denom; } @@ -1154,8 +1173,9 @@ int spa_alsa_start(struct state *state) init_loop(state); state->safety = 0.0; - spa_log_debug(state->log, NAME" %p: start %d duration:%d rate:%d slave:%d", - state, state->threshold, state->duration, state->rate_denom, state->slaved); + spa_log_debug(state->log, NAME" %p: start %d duration:%d rate:%d slave:%d match:%d", + state, state->threshold, state->duration, state->rate_denom, + state->slaved, state->matching); CHECK(set_swparams(state), "swparams"); if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_DEBUG))) diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 8605948f5..987e005e3 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -92,6 +92,7 @@ struct state { bool opened; snd_pcm_t *hndl; + int card; bool have_format; struct spa_audio_info current_format; @@ -135,6 +136,7 @@ struct state { unsigned int alsa_sync:1; unsigned int alsa_recovering:1; unsigned int slaved:1; + unsigned int matching:1; int64_t sample_count; diff --git a/spa/tests/test-node.c b/spa/tests/test-node.c index c67243e7a..63bf6f7c7 100644 --- a/spa/tests/test-node.c +++ b/spa/tests/test-node.c @@ -44,7 +44,7 @@ static void test_io_abi(void) spa_assert(sizeof(struct spa_io_buffers) == 8); spa_assert(sizeof(struct spa_io_memory) == 16); spa_assert(sizeof(struct spa_io_range) == 16); - spa_assert(sizeof(struct spa_io_clock) == 80); + spa_assert(sizeof(struct spa_io_clock) == 136); spa_assert(sizeof(struct spa_io_latency) == 24); spa_assert(sizeof(struct spa_io_sequence) == 16); spa_assert(sizeof(struct spa_io_segment_bar) == 96); @@ -56,7 +56,7 @@ static void test_io_abi(void) spa_assert(SPA_IO_POSITION_STATE_STARTING == 1); spa_assert(SPA_IO_POSITION_STATE_RUNNING == 2); - spa_assert(sizeof(struct spa_io_position) == 1952); + spa_assert(sizeof(struct spa_io_position) == 2008); spa_assert(sizeof(struct spa_io_rate_match) == 48); }