mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: improve resync
Use the max error to do a resync. Don't reset the dll, there is no reason for that. Don't use _rewind, but instead limit the amount of samples we read and write Should keep more stable sync in most cases.
This commit is contained in:
parent
87f4726164
commit
761199be70
1 changed files with 23 additions and 23 deletions
|
|
@ -1775,7 +1775,13 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
||||||
state, follower, state->last_threshold, state->threshold, diff, err);
|
state, follower, state->last_threshold, state->threshold, diff, err);
|
||||||
state->last_threshold = state->threshold;
|
state->last_threshold = state->threshold;
|
||||||
}
|
}
|
||||||
err = SPA_CLAMP(err, -state->max_error, state->max_error);
|
if (err > state->max_error) {
|
||||||
|
err = state->max_error;
|
||||||
|
state->alsa_sync = true;
|
||||||
|
} else if (err < -state->max_error) {
|
||||||
|
err = -state->max_error;
|
||||||
|
state->alsa_sync = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!follower || state->matching)
|
if (!follower || state->matching)
|
||||||
corr = spa_dll_update(&state->dll, err);
|
corr = spa_dll_update(&state->dll, err);
|
||||||
|
|
@ -1789,10 +1795,10 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
||||||
state->base_time = state->next_time;
|
state->base_time = state->next_time;
|
||||||
|
|
||||||
spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f "
|
spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f "
|
||||||
"bw:%f thr:%u del:%ld target:%ld err:%f",
|
"bw:%f thr:%u del:%ld target:%ld err:%f max:%f",
|
||||||
state->props.device, follower, state->matching,
|
state->props.device, follower, state->matching,
|
||||||
corr, state->dll.bw, state->threshold, delay, target,
|
corr, state->dll.bw, state->threshold, delay, target,
|
||||||
err);
|
err, state->max_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->rate_match) {
|
if (state->rate_match) {
|
||||||
|
|
@ -1862,12 +1868,14 @@ int spa_alsa_write(struct state *state)
|
||||||
{
|
{
|
||||||
snd_pcm_t *hndl = state->hndl;
|
snd_pcm_t *hndl = state->hndl;
|
||||||
const snd_pcm_channel_area_t *my_areas;
|
const snd_pcm_channel_area_t *my_areas;
|
||||||
snd_pcm_uframes_t written, frames, offset, off, to_write, total_written;
|
snd_pcm_uframes_t written, frames, offset, off, to_write, total_written, max_write;
|
||||||
snd_pcm_sframes_t commitres;
|
snd_pcm_sframes_t commitres;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
check_position_config(state);
|
check_position_config(state);
|
||||||
|
|
||||||
|
max_write = state->buffer_frames;
|
||||||
|
|
||||||
if (state->following && state->alsa_started) {
|
if (state->following && state->alsa_started) {
|
||||||
uint64_t current_time;
|
uint64_t current_time;
|
||||||
snd_pcm_uframes_t delay, target;
|
snd_pcm_uframes_t delay, target;
|
||||||
|
|
@ -1877,22 +1885,16 @@ int spa_alsa_write(struct state *state)
|
||||||
if (SPA_UNLIKELY((res = get_status(state, current_time, &delay, &target)) < 0))
|
if (SPA_UNLIKELY((res = get_status(state, current_time, &delay, &target)) < 0))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (SPA_UNLIKELY(!state->alsa_recovering && (delay < target / 2 || delay > 2 * target))) {
|
|
||||||
spa_dll_init(&state->dll);
|
|
||||||
state->alsa_sync = true;
|
|
||||||
}
|
|
||||||
if (SPA_UNLIKELY(state->alsa_sync)) {
|
if (SPA_UNLIKELY(state->alsa_sync)) {
|
||||||
spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
|
spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
|
||||||
state->props.device, delay, target, state->threshold);
|
state->props.device, delay, target, state->threshold);
|
||||||
target += state->threshold / 2;
|
|
||||||
if (delay > target)
|
if (delay > target)
|
||||||
snd_pcm_rewind(state->hndl, delay - target);
|
max_write = delay - target;
|
||||||
else
|
else if (delay < target)
|
||||||
spa_alsa_silence(state, target - delay);
|
spa_alsa_silence(state, target - delay);
|
||||||
delay = target;
|
delay = target;
|
||||||
state->alsa_sync = false;
|
state->alsa_sync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0))
|
if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -1900,8 +1902,8 @@ int spa_alsa_write(struct state *state)
|
||||||
total_written = 0;
|
total_written = 0;
|
||||||
again:
|
again:
|
||||||
|
|
||||||
frames = state->buffer_frames;
|
frames = max_write;
|
||||||
if (state->use_mmap) {
|
if (state->use_mmap && frames > 0) {
|
||||||
if (SPA_UNLIKELY((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0)) {
|
if (SPA_UNLIKELY((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0)) {
|
||||||
spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s",
|
spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s",
|
||||||
state->props.device, snd_strerror(res));
|
state->props.device, snd_strerror(res));
|
||||||
|
|
@ -2099,7 +2101,7 @@ push_frames(struct state *state,
|
||||||
int spa_alsa_read(struct state *state)
|
int spa_alsa_read(struct state *state)
|
||||||
{
|
{
|
||||||
snd_pcm_t *hndl = state->hndl;
|
snd_pcm_t *hndl = state->hndl;
|
||||||
snd_pcm_uframes_t total_read = 0, to_read;
|
snd_pcm_uframes_t total_read = 0, to_read, max_read;
|
||||||
const snd_pcm_channel_area_t *my_areas;
|
const snd_pcm_channel_area_t *my_areas;
|
||||||
snd_pcm_uframes_t read, frames, offset;
|
snd_pcm_uframes_t read, frames, offset;
|
||||||
snd_pcm_sframes_t commitres;
|
snd_pcm_sframes_t commitres;
|
||||||
|
|
@ -2123,6 +2125,8 @@ int spa_alsa_read(struct state *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max_read = state->buffer_frames;
|
||||||
|
|
||||||
if (state->following && state->alsa_started) {
|
if (state->following && state->alsa_started) {
|
||||||
uint64_t current_time;
|
uint64_t current_time;
|
||||||
snd_pcm_uframes_t delay, target;
|
snd_pcm_uframes_t delay, target;
|
||||||
|
|
@ -2133,16 +2137,11 @@ int spa_alsa_read(struct state *state)
|
||||||
if ((res = get_status(state, current_time, &delay, &target)) < 0)
|
if ((res = get_status(state, current_time, &delay, &target)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (!state->alsa_recovering && delay > target * 2) {
|
|
||||||
spa_dll_init(&state->dll);
|
|
||||||
state->alsa_sync = true;
|
|
||||||
}
|
|
||||||
if (state->alsa_sync) {
|
if (state->alsa_sync) {
|
||||||
spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync",
|
spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync",
|
||||||
state->props.device, delay, target, threshold);
|
state->props.device, delay, target, threshold);
|
||||||
target += threshold / 2;
|
|
||||||
if (delay < target)
|
if (delay < target)
|
||||||
snd_pcm_rewind(state->hndl, target - delay);
|
max_read = target - delay;
|
||||||
else if (delay > target)
|
else if (delay > target)
|
||||||
snd_pcm_forward(state->hndl, delay - target);
|
snd_pcm_forward(state->hndl, delay - target);
|
||||||
delay = target;
|
delay = target;
|
||||||
|
|
@ -2151,11 +2150,12 @@ int spa_alsa_read(struct state *state)
|
||||||
|
|
||||||
if ((res = update_time(state, current_time, delay, target, true)) < 0)
|
if ((res = update_time(state, current_time, delay, target, true)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (delay < state->read_size)
|
if (delay < state->read_size)
|
||||||
state->read_size = 0;
|
max_read = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
frames = state->read_size;
|
frames = SPA_MIN(max_read, state->read_size);
|
||||||
|
|
||||||
if (state->use_mmap) {
|
if (state->use_mmap) {
|
||||||
to_read = state->buffer_frames;
|
to_read = state->buffer_frames;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue