mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: fix rate match when using IRQ
When using the IRQ, we are woken up based on processed samples so compare expected and current clock times to rate match the clock. Fixes #3144
This commit is contained in:
parent
882f9ad2b3
commit
501a80b247
1 changed files with 32 additions and 25 deletions
|
|
@ -1935,10 +1935,15 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
|||
double err, corr;
|
||||
int32_t diff;
|
||||
|
||||
if (state->stream == SND_PCM_STREAM_PLAYBACK)
|
||||
err = delay - target;
|
||||
else
|
||||
err = target - delay;
|
||||
if (state->disable_tsched && !follower) {
|
||||
err = (int64_t)(current_time - state->next_time);
|
||||
err = err / 1e9 * state->rate;
|
||||
} else {
|
||||
if (state->stream == SND_PCM_STREAM_PLAYBACK)
|
||||
err = delay - target;
|
||||
else
|
||||
err = target - delay;
|
||||
}
|
||||
|
||||
if (SPA_UNLIKELY(state->dll.bw == 0.0)) {
|
||||
spa_dll_set_bw(&state->dll, SPA_DLL_BW_MAX, state->threshold, state->rate);
|
||||
|
|
@ -2514,6 +2519,14 @@ static int handle_capture(struct state *state, uint64_t current_time,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t get_time_ns(struct state *state)
|
||||
{
|
||||
struct timespec now;
|
||||
if (spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now) < 0)
|
||||
return 0;
|
||||
return SPA_TIMESPEC_TO_NSEC(&now);
|
||||
}
|
||||
|
||||
static void alsa_wakeup_event(struct spa_source *source)
|
||||
{
|
||||
struct state *state = source->data;
|
||||
|
|
@ -2526,6 +2539,8 @@ static void alsa_wakeup_event(struct spa_source *source)
|
|||
int err;
|
||||
unsigned short revents;
|
||||
|
||||
current_time = get_time_ns(state);
|
||||
|
||||
for (int i = 0; i < state->n_fds; i++) {
|
||||
state->pfds[i].revents = state->source[i].rmask;
|
||||
/* Reset so that we only handle all our sources' events once */
|
||||
|
|
@ -2543,17 +2558,20 @@ static void alsa_wakeup_event(struct spa_source *source)
|
|||
spa_log_trace_fp(state->log, "Woken up with no work to do");
|
||||
return;
|
||||
}
|
||||
} else if (SPA_LIKELY(state->started)) {
|
||||
if (SPA_UNLIKELY((res = spa_system_timerfd_read(state->data_system,
|
||||
} else {
|
||||
if (SPA_LIKELY(state->started)) {
|
||||
if (SPA_UNLIKELY((res = spa_system_timerfd_read(state->data_system,
|
||||
state->timerfd, &expire)) < 0)) {
|
||||
/* we can get here when the timer is changed since the last
|
||||
* timerfd wakeup, for example by do_reassign_follower() executed
|
||||
* in the same epoll wakeup cycle */
|
||||
if (res != -EAGAIN)
|
||||
spa_log_warn(state->log, "%p: error reading timerfd: %s",
|
||||
state, spa_strerror(res));
|
||||
return;
|
||||
* timerfd wakeup, for example by do_reassign_follower() executed
|
||||
* in the same epoll wakeup cycle */
|
||||
if (res != -EAGAIN)
|
||||
spa_log_warn(state->log, "%p: error reading timerfd: %s",
|
||||
state, spa_strerror(res));
|
||||
return;
|
||||
}
|
||||
}
|
||||
current_time = state->next_time;
|
||||
}
|
||||
|
||||
if (SPA_UNLIKELY((res = check_position_config(state)) < 0)) {
|
||||
|
|
@ -2562,8 +2580,6 @@ static void alsa_wakeup_event(struct spa_source *source)
|
|||
return;
|
||||
}
|
||||
|
||||
current_time = state->next_time;
|
||||
|
||||
if (SPA_UNLIKELY(get_status(state, current_time, &delay, &target) < 0)) {
|
||||
spa_log_error(state->log, "get_status error");
|
||||
state->next_time += state->threshold * 1e9 / state->rate;
|
||||
|
|
@ -2572,11 +2588,7 @@ static void alsa_wakeup_event(struct spa_source *source)
|
|||
|
||||
#ifndef FASTPATH
|
||||
if (SPA_UNLIKELY(spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_TRACE))) {
|
||||
struct timespec now;
|
||||
uint64_t nsec;
|
||||
if (spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now) < 0)
|
||||
return;
|
||||
nsec = SPA_TIMESPEC_TO_NSEC(&now);
|
||||
uint64_t nsec = get_time_ns(state);
|
||||
spa_log_trace_fp(state->log, "%p: wakeup %lu %lu %"PRIu64" %"PRIu64" %"PRIi64
|
||||
" %d %"PRIi64, state, delay, target, nsec, nsec,
|
||||
nsec - current_time, state->threshold, state->sample_count);
|
||||
|
|
@ -2636,12 +2648,7 @@ static void clear_period_sources(struct state *state) {
|
|||
|
||||
static int setup_sources(struct state *state)
|
||||
{
|
||||
struct timespec now;
|
||||
int res;
|
||||
|
||||
if ((res = spa_system_clock_gettime(state->data_system, CLOCK_MONOTONIC, &now)) < 0)
|
||||
return res;
|
||||
state->next_time = SPA_TIMESPEC_TO_NSEC(&now);
|
||||
state->next_time = get_time_ns(state);
|
||||
|
||||
if (state->following) {
|
||||
/* Disable wakeups from this node */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue