mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	alsa-seq: improve timings
Track the position of the clock instead of our own timer. Implement stop.
This commit is contained in:
		
							parent
							
								
									387b281f5c
								
							
						
					
					
						commit
						f0b3ed5257
					
				
					 2 changed files with 30 additions and 9 deletions
				
			
		| 
						 | 
					@ -130,6 +130,17 @@ static int seq_start(struct seq_state *state, struct seq_conn *conn)
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int seq_stop(struct seq_state *state, struct seq_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
						if ((res = snd_seq_stop_queue(conn->hndl, conn->queue_id, NULL)) < 0) {
 | 
				
			||||||
 | 
							spa_log_warn(state->log, "failed to stop queue: %s", snd_strerror(res));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						while (snd_seq_drain_output(conn->hndl) > 0)
 | 
				
			||||||
 | 
							sleep(1);
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int init_stream(struct seq_state *state, enum spa_direction direction)
 | 
					static int init_stream(struct seq_state *state, enum spa_direction direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct seq_stream *stream = &state->streams[direction];
 | 
						struct seq_stream *stream = &state->streams[direction];
 | 
				
			||||||
| 
						 | 
					@ -611,12 +622,15 @@ static void set_loop(struct seq_state *state, double bw)
 | 
				
			||||||
	state->bw = bw;
 | 
						state->bw = bw;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NSEC_TO_CLOCK(c,n) ((n) * (c)->rate.denom / ((c)->rate.num * SPA_NSEC_PER_SEC))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int update_time(struct seq_state *state, uint64_t nsec, bool slave)
 | 
					static int update_time(struct seq_state *state, uint64_t nsec, bool slave)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	snd_seq_queue_status_t *status;
 | 
						snd_seq_queue_status_t *status;
 | 
				
			||||||
	const snd_seq_real_time_t* queue_time;
 | 
						const snd_seq_real_time_t* queue_time;
 | 
				
			||||||
	uint64_t queue_real, queue_nsec;
 | 
						uint64_t queue_real;
 | 
				
			||||||
	double err, corr;
 | 
						double err, corr;
 | 
				
			||||||
 | 
						uint64_t clock_elapsed, queue_elapsed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* take queue time */
 | 
						/* take queue time */
 | 
				
			||||||
	snd_seq_queue_status_alloca(&status);
 | 
						snd_seq_queue_status_alloca(&status);
 | 
				
			||||||
| 
						 | 
					@ -624,13 +638,16 @@ static int update_time(struct seq_state *state, uint64_t nsec, bool slave)
 | 
				
			||||||
	queue_time = snd_seq_queue_status_get_real_time(status);
 | 
						queue_time = snd_seq_queue_status_get_real_time(status);
 | 
				
			||||||
	queue_real = SPA_TIMESPEC_TO_NSEC(queue_time);
 | 
						queue_real = SPA_TIMESPEC_TO_NSEC(queue_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->queue_start == 0)
 | 
						if (state->queue_base == 0) {
 | 
				
			||||||
		state->queue_start = state->current_time - queue_real;
 | 
							state->queue_base = nsec - queue_real;
 | 
				
			||||||
 | 
							state->clock_base = state->clock->position;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state->queue_time = state->current_time - state->queue_start;
 | 
						clock_elapsed = state->clock->position - state->clock_base;
 | 
				
			||||||
	queue_nsec = state->queue_start + queue_real;
 | 
						state->queue_time = nsec - state->queue_base;
 | 
				
			||||||
 | 
						queue_elapsed = NSEC_TO_CLOCK(state->clock, state->queue_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = ((int64_t)state->current_time - (int64_t) queue_nsec) / state->rate.denom;
 | 
						err = ((int64_t)clock_elapsed - (int64_t) queue_elapsed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (state->bw == 0.0) {
 | 
						if (state->bw == 0.0) {
 | 
				
			||||||
		set_loop(state, BW_MAX);
 | 
							set_loop(state, BW_MAX);
 | 
				
			||||||
| 
						 | 
					@ -657,7 +674,7 @@ static int update_time(struct seq_state *state, uint64_t nsec, bool slave)
 | 
				
			||||||
	state->next_time += state->threshold / corr * 1e9 / state->rate.denom;
 | 
						state->next_time += state->threshold / corr * 1e9 / state->rate.denom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!slave && state->clock) {
 | 
						if (!slave && state->clock) {
 | 
				
			||||||
		state->clock->nsec = state->current_time;
 | 
							state->clock->nsec = nsec;
 | 
				
			||||||
		state->clock->position += state->duration;
 | 
							state->clock->position += state->duration;
 | 
				
			||||||
		state->clock->duration = state->duration;
 | 
							state->clock->duration = state->duration;
 | 
				
			||||||
		state->clock->count = state->clock->position;
 | 
							state->clock->count = state->clock->position;
 | 
				
			||||||
| 
						 | 
					@ -667,7 +684,7 @@ static int update_time(struct seq_state *state, uint64_t nsec, bool slave)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_log_trace_fp(state->log, "now:%"PRIu64" queue:%"PRIu64" next:%"PRIu64" thr:%d",
 | 
						spa_log_trace_fp(state->log, "now:%"PRIu64" queue:%"PRIu64" next:%"PRIu64" thr:%d",
 | 
				
			||||||
			state->current_time, queue_nsec, state->next_time, state->threshold);
 | 
								nsec, queue_real, state->next_time, state->threshold);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -774,6 +791,7 @@ int spa_alsa_seq_start(struct seq_state *state)
 | 
				
			||||||
	state->source.rmask = 0;
 | 
						state->source.rmask = 0;
 | 
				
			||||||
	spa_loop_add_source(state->data_loop, &state->source);
 | 
						spa_loop_add_source(state->data_loop, &state->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state->queue_base = 0;
 | 
				
			||||||
	init_loop(state);
 | 
						init_loop(state);
 | 
				
			||||||
	set_timers(state);
 | 
						set_timers(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -834,6 +852,8 @@ int spa_alsa_seq_pause(struct seq_state *state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_loop_invoke(state->data_loop, do_remove_source, 0, NULL, 0, true, state);
 | 
						spa_loop_invoke(state->data_loop, do_remove_source, 0, NULL, 0, true, state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						seq_stop(state, &state->event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state->started = false;
 | 
						state->started = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,8 @@ struct seq_state {
 | 
				
			||||||
	uint64_t next_time;
 | 
						uint64_t next_time;
 | 
				
			||||||
	uint64_t base_time;
 | 
						uint64_t base_time;
 | 
				
			||||||
	uint64_t queue_time;
 | 
						uint64_t queue_time;
 | 
				
			||||||
	uint64_t queue_start;
 | 
						uint64_t queue_base;
 | 
				
			||||||
 | 
						uint64_t clock_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned int opened:1;
 | 
						unsigned int opened:1;
 | 
				
			||||||
	unsigned int started:1;
 | 
						unsigned int started:1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue