mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
spa: alsa: Try to get driver rate before setting up matching
In some cases, it is possible that the follower shares a clock with the
driver, but the driver rate is not known when the follower is assigned
to the driver. If this happens, then state->driver_rate is 0, and when
setting the format, we might think that we need to resample (because
follower rate != driver rate). This can cause us to incorrectly halve
the period size for the node.
This was introduced in commit 0b67c10a9c,
which forces reevaluation of matching status on driver change.
To avoid this, let us also probe for the driver rate when updating the
matching status, so we can make the update more accurate.
This commit is contained in:
parent
ef5d9ff028
commit
019b53ace8
1 changed files with 18 additions and 13 deletions
|
|
@ -2603,7 +2603,7 @@ static inline int do_start(struct state *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_position_config(struct state *state, bool starting);
|
||||
static inline int check_position_config(struct state *state, bool starting, bool check_driver_only);
|
||||
static void update_sources(struct state *state, bool active);
|
||||
|
||||
static int alsa_recover(struct state *state)
|
||||
|
|
@ -2671,7 +2671,7 @@ recover:
|
|||
spa_list_for_each(follower, &driver->rt.followers, rt.driver_link) {
|
||||
if (follower != driver && follower->linked) {
|
||||
do_drop(follower);
|
||||
check_position_config(follower, false);
|
||||
check_position_config(follower, false, false);
|
||||
}
|
||||
}
|
||||
do_prepare(driver);
|
||||
|
|
@ -2907,6 +2907,8 @@ static int setup_matching(struct state *state)
|
|||
spa_log_debug(state->log, "driver clock:'%s' our clock:'%s'",
|
||||
state->position->clock.name, state->clock_name);
|
||||
|
||||
check_position_config(state, false, true);
|
||||
|
||||
if (spa_streq(state->position->clock.name, state->clock_name))
|
||||
state->matching = false;
|
||||
|
||||
|
|
@ -2931,7 +2933,7 @@ static void update_sources(struct state *state, bool active)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int check_position_config(struct state *state, bool starting)
|
||||
static inline int check_position_config(struct state *state, bool starting, bool check_driver_only)
|
||||
{
|
||||
uint64_t target_duration;
|
||||
struct spa_fraction target_rate;
|
||||
|
|
@ -2965,13 +2967,16 @@ static inline int check_position_config(struct state *state, bool starting)
|
|||
|
||||
state->driver_duration = target_duration;
|
||||
state->driver_rate = target_rate;
|
||||
state->threshold = SPA_SCALE32_UP(state->driver_duration, state->rate, state->driver_rate.denom);
|
||||
state->max_error = SPA_MAX(256.0f, (state->threshold + state->headroom) / 2.0f);
|
||||
state->max_resync = SPA_MIN(state->threshold + state->headroom, state->max_error);
|
||||
state->err_wdw = (double)state->driver_rate.denom/state->driver_duration;
|
||||
state->resample = !state->pitch_elem &&
|
||||
(((uint32_t)state->rate != state->driver_rate.denom) || state->matching);
|
||||
state->alsa_sync = true;
|
||||
|
||||
if (!check_driver_only) {
|
||||
state->threshold = SPA_SCALE32_UP(state->driver_duration, state->rate, state->driver_rate.denom);
|
||||
state->max_error = SPA_MAX(256.0f, (state->threshold + state->headroom) / 2.0f);
|
||||
state->max_resync = SPA_MIN(state->threshold + state->headroom, state->max_error);
|
||||
state->err_wdw = (double)state->driver_rate.denom/state->driver_duration;
|
||||
state->resample = !state->pitch_elem &&
|
||||
(((uint32_t)state->rate != state->driver_rate.denom) || state->matching);
|
||||
state->alsa_sync = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2982,7 +2987,7 @@ static int alsa_write_sync(struct state *state, uint64_t current_time)
|
|||
snd_pcm_uframes_t avail, delay, target;
|
||||
bool following = state->following;
|
||||
|
||||
if (SPA_UNLIKELY((res = check_position_config(state, false)) < 0))
|
||||
if (SPA_UNLIKELY((res = check_position_config(state, false, false)) < 0))
|
||||
return res;
|
||||
|
||||
if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) {
|
||||
|
|
@ -3249,7 +3254,7 @@ static int alsa_read_sync(struct state *state, uint64_t current_time)
|
|||
if (SPA_UNLIKELY(!state->alsa_started))
|
||||
return 0;
|
||||
|
||||
if (SPA_UNLIKELY((res = check_position_config(state, false)) < 0))
|
||||
if (SPA_UNLIKELY((res = check_position_config(state, false, false)) < 0))
|
||||
return res;
|
||||
|
||||
if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) {
|
||||
|
|
@ -3659,7 +3664,7 @@ int spa_alsa_prepare(struct state *state)
|
|||
if (state->prepared)
|
||||
return 0;
|
||||
|
||||
if (check_position_config(state, true) < 0) {
|
||||
if (check_position_config(state, true, false) < 0) {
|
||||
spa_log_error(state->log, "%s: invalid position config", state->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue