mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	audio-src: test stream timings
This commit is contained in:
		
							parent
							
								
									ee05daea53
								
							
						
					
					
						commit
						150c1cc05d
					
				
					 1 changed files with 41 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
 | 
			
		||||
#define M_PI_M2 ( M_PI + M_PI )
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_QUANTUM		1764
 | 
			
		||||
#define DEFAULT_RATE		44100
 | 
			
		||||
#define DEFAULT_CHANNELS	2
 | 
			
		||||
#define DEFAULT_VOLUME		0.7
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +29,7 @@ struct data {
 | 
			
		|||
	struct pw_stream *stream;
 | 
			
		||||
 | 
			
		||||
	double accumulator;
 | 
			
		||||
	uint64_t outputSample;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void fill_f32(struct data *d, void *dest, int n_frames)
 | 
			
		||||
| 
						 | 
				
			
			@ -63,17 +65,41 @@ static void on_process(void *userdata)
 | 
			
		|||
	int n_frames, stride;
 | 
			
		||||
	uint8_t *p;
 | 
			
		||||
 | 
			
		||||
	struct pw_time streamTime;
 | 
			
		||||
	uint64_t driverSample;
 | 
			
		||||
	int64_t queued;
 | 
			
		||||
 | 
			
		||||
	pw_stream_get_time_n(data->stream, &streamTime, sizeof(streamTime));
 | 
			
		||||
 | 
			
		||||
	if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) {
 | 
			
		||||
		pw_log_warn("out of buffers: %m");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* calculate the current sample in the driver's timeline */
 | 
			
		||||
	driverSample = streamTime.ticks * DEFAULT_RATE * streamTime.rate.num / streamTime.rate.denom;
 | 
			
		||||
 | 
			
		||||
	/* find how many samples we have queued but have not yet appeared in the driver's timeline;
 | 
			
		||||
	   these are queued in the audioadapter but pw_stream doesn't report them accurately */
 | 
			
		||||
	queued = data->outputSample - driverSample;
 | 
			
		||||
	if (queued < 0) {
 | 
			
		||||
		/* XRun, resync our timeline */
 | 
			
		||||
		pw_log_info("XRun! resync, data->outputSample += %"PRIi64, -queued);
 | 
			
		||||
		data->outputSample += -queued;
 | 
			
		||||
		queued = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pw_log_info("process, b.req %"PRIu64", s.ticks %"PRIu64 ", sample(our) %"PRIu64", sample(dr) %"PRIu64",\n"
 | 
			
		||||
		    "         s.buf %"PRIu64 ", s.queued %"PRIu64 ", queued (real) %"PRIi64 ", s.delay %"PRIu64,
 | 
			
		||||
		    b->requested, streamTime.ticks, data->outputSample, driverSample,
 | 
			
		||||
		    streamTime.buffered, streamTime.queued, queued, streamTime.delay);
 | 
			
		||||
 | 
			
		||||
	buf = b->buffer;
 | 
			
		||||
	if ((p = buf->datas[0].data) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	stride = sizeof(float) * DEFAULT_CHANNELS;
 | 
			
		||||
	n_frames = SPA_MIN(b->requested, buf->datas[0].maxsize / stride);
 | 
			
		||||
	n_frames = SPA_MIN((uint64_t) DEFAULT_QUANTUM, buf->datas[0].maxsize / stride);
 | 
			
		||||
 | 
			
		||||
	fill_f32(data, p, n_frames);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +107,9 @@ static void on_process(void *userdata)
 | 
			
		|||
	buf->datas[0].chunk->stride = stride;
 | 
			
		||||
	buf->datas[0].chunk->size = n_frames * stride;
 | 
			
		||||
 | 
			
		||||
	b->size = n_frames;
 | 
			
		||||
	data->outputSample += n_frames;
 | 
			
		||||
 | 
			
		||||
	pw_stream_queue_buffer(data->stream, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +127,7 @@ static void do_quit(void *userdata, int signal_number)
 | 
			
		|||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	struct data data = { 0, };
 | 
			
		||||
	const struct spa_pod *params[1];
 | 
			
		||||
	const struct spa_pod *params[2];
 | 
			
		||||
	uint8_t buffer[1024];
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
	struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
 | 
			
		||||
| 
						 | 
				
			
			@ -126,6 +155,7 @@ int main(int argc, char *argv[])
 | 
			
		|||
	props = pw_properties_new(PW_KEY_MEDIA_TYPE, "Audio",
 | 
			
		||||
			PW_KEY_MEDIA_CATEGORY, "Playback",
 | 
			
		||||
			PW_KEY_MEDIA_ROLE, "Music",
 | 
			
		||||
			PW_KEY_NODE_LATENCY, SPA_STRINGIFY (DEFAULT_QUANTUM) "/" SPA_STRINGIFY (DEFAULT_RATE),
 | 
			
		||||
			NULL);
 | 
			
		||||
	if (argc > 1)
 | 
			
		||||
		/* Set stream target if given on command line */
 | 
			
		||||
| 
						 | 
				
			
			@ -144,6 +174,13 @@ int main(int argc, char *argv[])
 | 
			
		|||
				.format = SPA_AUDIO_FORMAT_F32,
 | 
			
		||||
				.channels = DEFAULT_CHANNELS,
 | 
			
		||||
				.rate = DEFAULT_RATE ));
 | 
			
		||||
	params[1] = spa_pod_builder_add_object(&b,
 | 
			
		||||
			SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
 | 
			
		||||
			SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(4),
 | 
			
		||||
			SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
 | 
			
		||||
			SPA_PARAM_BUFFERS_size,    SPA_POD_Int(DEFAULT_QUANTUM * sizeof(float) * DEFAULT_CHANNELS),
 | 
			
		||||
			SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(sizeof(float) * DEFAULT_CHANNELS),
 | 
			
		||||
			SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int((1<<SPA_DATA_MemPtr)));
 | 
			
		||||
 | 
			
		||||
	/* Now connect this stream. We ask that our process function is
 | 
			
		||||
	 * called in a realtime thread. */
 | 
			
		||||
| 
						 | 
				
			
			@ -151,9 +188,8 @@ int main(int argc, char *argv[])
 | 
			
		|||
			  PW_DIRECTION_OUTPUT,
 | 
			
		||||
			  PW_ID_ANY,
 | 
			
		||||
			  PW_STREAM_FLAG_AUTOCONNECT |
 | 
			
		||||
			  PW_STREAM_FLAG_MAP_BUFFERS |
 | 
			
		||||
			  PW_STREAM_FLAG_RT_PROCESS,
 | 
			
		||||
			  params, 1);
 | 
			
		||||
			  PW_STREAM_FLAG_MAP_BUFFERS,
 | 
			
		||||
			  params, 2);
 | 
			
		||||
 | 
			
		||||
	/* and wait while we let things run */
 | 
			
		||||
	pw_main_loop_run(data.loop);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue