alsa: also use interpolated time as nsec in IRQ mode
Don't use the current time as the nsec field in the graph clock because it can jitter a lot. Instead, use the smoothed next_time, like we do for timer based scheduling. Since we track the current time against the rate converted ideal time, lock on to the first timestamp when we reset the dll. See #3657
This commit is contained in:
parent
0c857f5455
commit
49cdb468c2
|
@ -2531,6 +2531,15 @@ static int get_status(struct state *state, uint64_t current_time, snd_pcm_uframe
|
|||
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 int update_time(struct state *state, uint64_t current_time, snd_pcm_sframes_t delay,
|
||||
snd_pcm_sframes_t target, bool follower)
|
||||
{
|
||||
|
@ -2538,8 +2547,15 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
|||
int32_t diff;
|
||||
|
||||
if (state->disable_tsched && !follower) {
|
||||
err = (int64_t)(current_time - state->next_time);
|
||||
err = err / 1e9 * state->rate;
|
||||
uint64_t now = get_time_ns(state);
|
||||
|
||||
if (SPA_UNLIKELY(state->dll.bw == 0.0)) {
|
||||
current_time = now;
|
||||
err = 0.0;
|
||||
} else {
|
||||
err = (int64_t)(now - current_time);
|
||||
err = err / 1e9 * state->rate;
|
||||
}
|
||||
} else {
|
||||
if (state->stream == SND_PCM_STREAM_PLAYBACK)
|
||||
err = delay - target;
|
||||
|
@ -3166,14 +3182,6 @@ static int capture_ready(struct state *state)
|
|||
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, *follower;
|
||||
|
@ -3185,8 +3193,6 @@ 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 */
|
||||
|
@ -3222,8 +3228,8 @@ static void alsa_wakeup_event(struct spa_source *source)
|
|||
return;
|
||||
}
|
||||
}
|
||||
current_time = state->next_time;
|
||||
}
|
||||
current_time = state->next_time;
|
||||
|
||||
/* first do all the sync */
|
||||
if (state->stream == SND_PCM_STREAM_CAPTURE)
|
||||
|
|
Loading…
Reference in New Issue