diff options
-rw-r--r-- | spa/plugins/alsa/alsa-utils.c | 74 | ||||
-rw-r--r-- | spa/plugins/alsa/alsa-utils.h | 3 | ||||
-rw-r--r-- | src/pipewire/node.c | 1 |
3 files changed, 46 insertions, 32 deletions
diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index fa197c41..d5a7d24a 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -542,6 +542,8 @@ static int alsa_recover(struct state *state, int err) spa_log_error(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64" %f", state, xrun, missing, state->safety); + + state->sample_count += missing ? missing : state->threshold; break; } default: @@ -623,8 +625,9 @@ static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t del else if (state->bw == BW_MED) set_loop(state, BW_MIN); - spa_log_debug(state->log, "slave:%d rate:%f bw:%f err:%f (%f %f %f)", - slave, corr, state->bw, err, state->z1, state->z2, state->z3); + spa_log_debug(state->log, "slave:%d rate:%f bw:%f thr:%d err:%f (%f %f %f)", + slave, corr, state->bw, state->threshold, + err, state->z1, state->z2, state->z3); } if (slave && state->notify) { @@ -675,7 +678,7 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence) return res; if (delay > state->threshold * 2) { - spa_log_warn(state->log, "slave: resync %f %f %f", + spa_log_warn(state->log, "slave delay:%ld resync %f %f %f", delay, state->z1, state->z2, state->z3); init_loop(state); state->alsa_sync = true; @@ -819,18 +822,22 @@ push_frames(struct state *state, d = b->buf->datas; - src = SPA_MEMBER(my_areas[0].addr, offset * state->frame_size, uint8_t); avail = d[0].maxsize / state->frame_size; total_frames = SPA_MIN(avail, state->threshold); n_bytes = total_frames * state->frame_size; - l0 = SPA_MIN(n_bytes, frames * state->frame_size); - l1 = n_bytes - l0; + if (my_areas) { + l0 = SPA_MIN(n_bytes, frames * state->frame_size); + l1 = n_bytes - l0; - spa_memcpy(d[0].data, src, l0); - if (l1 > 0) - spa_memcpy(d[0].data, my_areas[0].addr, l1); + src = SPA_MEMBER(my_areas[0].addr, offset * state->frame_size, uint8_t); + spa_memcpy(d[0].data, src, l0); + if (l1 > 0) + spa_memcpy(d[0].data, my_areas[0].addr, l1); + } else { + memset(d[0].data, 0, n_bytes); + } d[0].chunk->offset = 0; d[0].chunk->size = n_bytes; @@ -851,29 +858,44 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence) snd_pcm_uframes_t read, frames, offset; int res; - if (state->position && state->threshold != state->position->size) - state->threshold = state->position->size; + if (state->position) { + uint64_t position; + + if (state->threshold != state->position->size) { + state->threshold = state->position->size; + } + position = state->position->clock.position; + if (state->last_position && state->last_position + state->last_threshold != position) { + state->alsa_sync = true; + spa_log_warn(state->log, "discont, resync %"PRIu64" %"PRIu64" %d", + state->last_position, position, state->last_threshold); + } + state->last_position = position; + } if (state->slaved && state->alsa_started) { uint64_t nsec; snd_pcm_sframes_t delay; + uint32_t threshold = state->threshold; if ((res = get_status(state, &delay)) < 0) return res; - if (delay < state->threshold || delay > state->threshold * 2) { - spa_log_warn(state->log, "slave: resync %f %f %f", + if (delay < threshold) { + spa_log_warn(state->log, "slave delay:%ld resync %f %f %f", delay, state->z1, state->z2, state->z3); init_loop(state); - state->alsa_sync = true; + push_frames(state, NULL, 0, 0); + return 0; } if (state->alsa_sync) { - if (delay < state->threshold) - snd_pcm_rewind(state->hndl, state->threshold - delay); - else if (delay > state->threshold) - snd_pcm_forward(state->hndl, delay - state->threshold); + spa_log_warn(state->log, "slave resync %ld %d", delay, threshold); + if (delay < threshold) + snd_pcm_rewind(state->hndl, threshold - delay); + else if (delay > threshold) + snd_pcm_forward(state->hndl, delay - threshold); - delay = state->threshold; + delay = threshold; state->alsa_sync = false; } @@ -882,34 +904,26 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence) return res; } -again: to_read = state->buffer_frames; if ((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &to_read)) < 0) { spa_log_error(state->log, "snd_pcm_mmap_begin error: %s", snd_strerror(res)); return res; } frames = SPA_MIN(to_read, state->threshold); - spa_log_trace_fp(state->log, "begin %ld %ld %d", offset, frames, state->threshold); + + spa_log_trace_fp(state->log, "begin %ld %ld %ld %d", offset, frames, to_read, state->threshold); read = push_frames(state, my_areas, offset, frames); spa_log_trace_fp(state->log, "commit %ld %ld %"PRIi64, offset, read, state->sample_count); total_read += read; - if ((res = snd_pcm_mmap_commit(hndl, offset, read)) < 0) { + if ((res = snd_pcm_mmap_commit(hndl, offset, frames)) < 0) { spa_log_error(state->log, "snd_pcm_mmap_commit error: %s", snd_strerror(res)); if (res != -EPIPE && res != -ESTRPIPE) return res; } - if (to_read > read) - to_read -= read; - else - to_read = 0; - - if (read > 0 && to_read >= state->threshold && !spa_list_is_empty(&state->free)) - goto again; - state->sample_count += total_read; return 0; diff --git a/spa/plugins/alsa/alsa-utils.h b/spa/plugins/alsa/alsa-utils.h index 5ef42caa..d307c9a9 100644 --- a/spa/plugins/alsa/alsa-utils.h +++ b/spa/plugins/alsa/alsa-utils.h @@ -65,7 +65,7 @@ struct buffer { struct spa_list link; }; -#define BW_MAX 0.256 +#define BW_MAX 0.128 #define BW_MED 0.064 #define BW_MIN 0.016 #define BW_PERIOD (3 * SPA_NSEC_PER_SEC) @@ -125,6 +125,7 @@ struct state { int timerfd; uint32_t threshold; uint32_t last_threshold; + uint64_t last_position; unsigned int alsa_started:1; unsigned int alsa_sync:1; unsigned int slaved:1; diff --git a/src/pipewire/node.c b/src/pipewire/node.c index ebfdc897..921939cd 100644 --- a/src/pipewire/node.c +++ b/src/pipewire/node.c @@ -49,7 +49,6 @@ struct impl { struct pw_work_queue *work; - uint32_t next_position; int last_error; unsigned int pause_on_idle:1; |