summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spa/plugins/alsa/alsa-utils.c74
-rw-r--r--spa/plugins/alsa/alsa-utils.h3
-rw-r--r--src/pipewire/node.c1
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;