mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-10-29 05:40:27 -04:00 
			
		
		
		
	alsa: improve capture resync
Make sure we capture enough data even when the ringbuffer wraps around. Use the clock nsec to get timing, we don't need to get the new time. Improve sync in capture.
This commit is contained in:
		
							parent
							
								
									317fd9fac5
								
							
						
					
					
						commit
						b43844e7c6
					
				
					 1 changed files with 26 additions and 19 deletions
				
			
		|  | @ -671,7 +671,6 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence) | ||||||
| 		uint64_t nsec; | 		uint64_t nsec; | ||||||
| 		snd_pcm_sframes_t delay; | 		snd_pcm_sframes_t delay; | ||||||
| 
 | 
 | ||||||
| 		clock_gettime(CLOCK_MONOTONIC, &state->now); |  | ||||||
| 		if ((res = get_status(state, &delay)) < 0) | 		if ((res = get_status(state, &delay)) < 0) | ||||||
| 			return res; | 			return res; | ||||||
| 
 | 
 | ||||||
|  | @ -691,7 +690,7 @@ int spa_alsa_write(struct state *state, snd_pcm_uframes_t silence) | ||||||
| 			state->alsa_sync = false; | 			state->alsa_sync = false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		nsec = SPA_TIMESPEC_TO_NSEC(&state->now); | 		nsec = state->position->clock.nsec; | ||||||
| 		if ((res = update_time(state, nsec, delay, true)) < 0) | 		if ((res = update_time(state, nsec, delay, true)) < 0) | ||||||
| 			return res; | 			return res; | ||||||
| 	} | 	} | ||||||
|  | @ -807,7 +806,7 @@ push_frames(struct state *state, | ||||||
| 		size_t n_bytes; | 		size_t n_bytes; | ||||||
| 		struct buffer *b; | 		struct buffer *b; | ||||||
| 		struct spa_data *d; | 		struct spa_data *d; | ||||||
| 		uint32_t index, offs, avail, l0, l1; | 		uint32_t avail, l0, l1; | ||||||
| 
 | 
 | ||||||
| 		b = spa_list_first(&state->free, struct buffer, link); | 		b = spa_list_first(&state->free, struct buffer, link); | ||||||
| 		spa_list_remove(&b->link); | 		spa_list_remove(&b->link); | ||||||
|  | @ -823,19 +822,17 @@ push_frames(struct state *state, | ||||||
| 		src = SPA_MEMBER(my_areas[0].addr, offset * state->frame_size, uint8_t); | 		src = SPA_MEMBER(my_areas[0].addr, offset * state->frame_size, uint8_t); | ||||||
| 
 | 
 | ||||||
| 		avail = d[0].maxsize / state->frame_size; | 		avail = d[0].maxsize / state->frame_size; | ||||||
| 		index = 0; | 		total_frames = SPA_MIN(avail, state->threshold); | ||||||
| 		total_frames = SPA_MIN(avail, frames); |  | ||||||
| 		n_bytes = total_frames * state->frame_size; | 		n_bytes = total_frames * state->frame_size; | ||||||
| 
 | 
 | ||||||
| 		offs = index % d[0].maxsize; | 		l0 = SPA_MIN(n_bytes, frames * state->frame_size); | ||||||
| 		l0 = SPA_MIN(n_bytes, d[0].maxsize - offs); |  | ||||||
| 		l1 = n_bytes - l0; | 		l1 = n_bytes - l0; | ||||||
| 
 | 
 | ||||||
| 		spa_memcpy(SPA_MEMBER(d[0].data, offs, void), src, l0); | 		spa_memcpy(d[0].data, src, l0); | ||||||
| 		if (l1 > 0) | 		if (l1 > 0) | ||||||
| 			spa_memcpy(d[0].data, src + l0, l1); | 			spa_memcpy(d[0].data, my_areas[0].addr, l1); | ||||||
| 
 | 
 | ||||||
| 		d[0].chunk->offset = index; | 		d[0].chunk->offset = 0; | ||||||
| 		d[0].chunk->size = n_bytes; | 		d[0].chunk->size = n_bytes; | ||||||
| 		d[0].chunk->stride = state->frame_size; | 		d[0].chunk->stride = state->frame_size; | ||||||
| 
 | 
 | ||||||
|  | @ -857,24 +854,30 @@ int spa_alsa_read(struct state *state, snd_pcm_uframes_t silence) | ||||||
| 	if (state->position && state->threshold != state->position->size) | 	if (state->position && state->threshold != state->position->size) | ||||||
| 		state->threshold = state->position->size; | 		state->threshold = state->position->size; | ||||||
| 
 | 
 | ||||||
| 	if (state->slaved) { | 	if (state->slaved && state->alsa_started) { | ||||||
| 		uint64_t nsec, master; | 		uint64_t nsec; | ||||||
| 		snd_pcm_sframes_t delay; | 		snd_pcm_sframes_t delay; | ||||||
| 
 | 
 | ||||||
| 		master = state->position->clock.position + state->position->clock.delay; |  | ||||||
| 		nsec = master * SPA_NSEC_PER_SEC / state->rate; |  | ||||||
| 
 |  | ||||||
| 		if ((res = get_status(state, &delay)) < 0) | 		if ((res = get_status(state, &delay)) < 0) | ||||||
| 			return res; | 			return res; | ||||||
| 
 | 
 | ||||||
| 		if (delay > state->threshold * 2) { | 		if (delay < state->threshold || delay > state->threshold * 2) { | ||||||
| 			spa_log_warn(state->log, "slave: resync %f %f %f", | 			spa_log_warn(state->log, "slave: resync %f %f %f", | ||||||
| 					state->z1, state->z2, state->z3); | 					state->z1, state->z2, state->z3); | ||||||
| 			snd_pcm_forward(state->hndl, delay - state->threshold); |  | ||||||
| 			delay = state->threshold; |  | ||||||
| 			init_loop(state); | 			init_loop(state); | ||||||
|  | 			state->alsa_sync = true; | ||||||
|  | 		} | ||||||
|  | 		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); | ||||||
|  | 
 | ||||||
|  | 			delay = state->threshold; | ||||||
|  | 			state->alsa_sync = false; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		nsec = state->position->clock.nsec; | ||||||
| 		if ((res = update_time(state, nsec, delay, true)) < 0) | 		if ((res = update_time(state, nsec, delay, true)) < 0) | ||||||
| 			return res; | 			return res; | ||||||
| 	} | 	} | ||||||
|  | @ -899,7 +902,11 @@ again: | ||||||
| 			return res; | 			return res; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	to_read -= read; | 	if (to_read > read) | ||||||
|  | 		to_read -= read; | ||||||
|  | 	else | ||||||
|  | 		to_read = 0; | ||||||
|  | 
 | ||||||
| 	if (read > 0 && to_read >= state->threshold && !spa_list_is_empty(&state->free)) | 	if (read > 0 && to_read >= state->threshold && !spa_list_is_empty(&state->free)) | ||||||
| 		goto again; | 		goto again; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Wim Taymans
						Wim Taymans