mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-01 22:58:47 -04: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