mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Solaris: fixed latency (resent)
Set a fixed latency based on the given buffer size, which is constrained to the 128 KB limit on buffered writes. Also fix an error path.
This commit is contained in:
		
							parent
							
								
									87d2dded9b
								
							
						
					
					
						commit
						601fb63b01
					
				
					 1 changed files with 30 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -136,6 +136,9 @@ static const char* const valid_modargs[] = {
 | 
			
		|||
#define MAX_RENDER_HZ   (300)
 | 
			
		||||
/* This render rate limit imposes a minimum latency, but without it we waste too much CPU time. */
 | 
			
		||||
 | 
			
		||||
#define MAX_BUFFER_SIZE (128 * 1024)
 | 
			
		||||
/* An attempt to buffer more than 128 KB causes write() to fail with errno == EAGAIN. */
 | 
			
		||||
 | 
			
		||||
static uint64_t get_playback_buffered_bytes(struct userdata *u) {
 | 
			
		||||
    audio_info_t info;
 | 
			
		||||
    uint64_t played_bytes;
 | 
			
		||||
| 
						 | 
				
			
			@ -651,6 +654,7 @@ static void thread_func(void *userdata) {
 | 
			
		|||
                void *p;
 | 
			
		||||
                ssize_t w;
 | 
			
		||||
                size_t len;
 | 
			
		||||
                int write_type = 1;
 | 
			
		||||
 | 
			
		||||
                /*
 | 
			
		||||
                 * Since we cannot modify the size of the output buffer we fake it
 | 
			
		||||
| 
						 | 
				
			
			@ -668,38 +672,31 @@ static void thread_func(void *userdata) {
 | 
			
		|||
                    break;
 | 
			
		||||
 | 
			
		||||
                if (u->memchunk.length < len)
 | 
			
		||||
                    pa_sink_render(u->sink, u->sink->thread_info.max_request, &u->memchunk);
 | 
			
		||||
                    pa_sink_render(u->sink, len - u->memchunk.length, &u->memchunk);
 | 
			
		||||
 | 
			
		||||
                len = PA_MIN(u->memchunk.length, len);
 | 
			
		||||
 | 
			
		||||
                p = pa_memblock_acquire(u->memchunk.memblock);
 | 
			
		||||
                w = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, NULL);
 | 
			
		||||
                w = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, len, &write_type);
 | 
			
		||||
                pa_memblock_release(u->memchunk.memblock);
 | 
			
		||||
 | 
			
		||||
                if (w <= 0) {
 | 
			
		||||
                    switch (errno) {
 | 
			
		||||
                        case EINTR:
 | 
			
		||||
                            continue;
 | 
			
		||||
                        case EAGAIN:
 | 
			
		||||
                            /* If the buffer_size is too big, we get EAGAIN. Avoiding that limit by trial and error
 | 
			
		||||
                             * is not ideal, but I don't know how to get the system to tell me what the limit is.
 | 
			
		||||
                             */
 | 
			
		||||
                            u->buffer_size = u->buffer_size * 18 / 25;
 | 
			
		||||
                            u->buffer_size -= u->buffer_size % u->frame_size;
 | 
			
		||||
                            u->buffer_size = PA_MAX(u->buffer_size, 2 * u->minimum_request);
 | 
			
		||||
                            pa_sink_set_max_request_within_thread(u->sink, u->buffer_size);
 | 
			
		||||
                            pa_sink_set_max_rewind_within_thread(u->sink, u->buffer_size);
 | 
			
		||||
                            pa_log("EAGAIN. Buffer size is now %u bytes (%llu buffered)", u->buffer_size, buffered_bytes);
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
 | 
			
		||||
                            goto fail;
 | 
			
		||||
                    if (errno == EINTR) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    } else if (errno == EAGAIN) {
 | 
			
		||||
                        /* We may have realtime priority so yield the CPU to ensure that fd can become writable again. */
 | 
			
		||||
                        pa_log_debug("EAGAIN with %llu bytes buffered.", buffered_bytes);
 | 
			
		||||
                        break;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
 | 
			
		||||
                        goto fail;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    pa_assert(w % u->frame_size == 0);
 | 
			
		||||
 | 
			
		||||
                    u->written_bytes += w;
 | 
			
		||||
                    u->memchunk.length -= w;
 | 
			
		||||
 | 
			
		||||
                    u->memchunk.index += w;
 | 
			
		||||
                    u->memchunk.length -= w;
 | 
			
		||||
                    if (u->memchunk.length <= 0) {
 | 
			
		||||
                        pa_memblock_unref(u->memchunk.memblock);
 | 
			
		||||
                        pa_memchunk_reset(&u->memchunk);
 | 
			
		||||
| 
						 | 
				
			
			@ -830,7 +827,7 @@ int pa__init(pa_module *m) {
 | 
			
		|||
    pa_channel_map map;
 | 
			
		||||
    pa_modargs *ma = NULL;
 | 
			
		||||
    uint32_t buffer_length_msec;
 | 
			
		||||
    int fd;
 | 
			
		||||
    int fd = -1;
 | 
			
		||||
    pa_sink_new_data sink_new_data;
 | 
			
		||||
    pa_source_new_data source_new_data;
 | 
			
		||||
    char const *name;
 | 
			
		||||
| 
						 | 
				
			
			@ -882,7 +879,13 @@ int pa__init(pa_module *m) {
 | 
			
		|||
    }
 | 
			
		||||
    u->buffer_size = pa_usec_to_bytes(1000 * buffer_length_msec, &ss);
 | 
			
		||||
    if (u->buffer_size < 2 * u->minimum_request) {
 | 
			
		||||
        pa_log("supplied buffer size argument is too small");
 | 
			
		||||
        pa_log("buffer_length argument cannot be smaller than %u",
 | 
			
		||||
               (unsigned)(pa_bytes_to_usec(2 * u->minimum_request, &ss) / 1000));
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    if (u->buffer_size > MAX_BUFFER_SIZE) {
 | 
			
		||||
        pa_log("buffer_length argument cannot be greater than %u",
 | 
			
		||||
               (unsigned)(pa_bytes_to_usec(MAX_BUFFER_SIZE, &ss) / 1000));
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -945,6 +948,7 @@ int pa__init(pa_module *m) {
 | 
			
		|||
 | 
			
		||||
        pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
 | 
			
		||||
        pa_source_set_rtpoll(u->source, u->rtpoll);
 | 
			
		||||
        pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &u->source->sample_spec));
 | 
			
		||||
 | 
			
		||||
        u->source->get_volume = source_get_volume;
 | 
			
		||||
        u->source->set_volume = source_set_volume;
 | 
			
		||||
| 
						 | 
				
			
			@ -987,15 +991,15 @@ int pa__init(pa_module *m) {
 | 
			
		|||
 | 
			
		||||
        pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
 | 
			
		||||
        pa_sink_set_rtpoll(u->sink, u->rtpoll);
 | 
			
		||||
        pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec));
 | 
			
		||||
        pa_sink_set_max_request(u->sink, u->buffer_size);
 | 
			
		||||
        pa_sink_set_max_rewind(u->sink, u->buffer_size);
 | 
			
		||||
 | 
			
		||||
        u->sink->get_volume = sink_get_volume;
 | 
			
		||||
        u->sink->set_volume = sink_set_volume;
 | 
			
		||||
        u->sink->get_mute = sink_get_mute;
 | 
			
		||||
        u->sink->set_mute = sink_set_mute;
 | 
			
		||||
        u->sink->refresh_volume = u->sink->refresh_muted = TRUE;
 | 
			
		||||
 | 
			
		||||
        pa_sink_set_max_request(u->sink, u->buffer_size);
 | 
			
		||||
        pa_sink_set_max_rewind(u->sink, u->buffer_size);
 | 
			
		||||
    } else
 | 
			
		||||
        u->sink = NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue