Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
* Add some default values if client passes -1 in buffer attributes for
  a stream;
* Ask client for data only if we are ready to get at least minreq bytes.

Although minreq is described as "minimum request" in API documentation,
Firefox seem to be expecting to be called back on every minreq byte
chunk. Larger amount returned result in degraded frames per second
count.
  • Loading branch information
i-rinat committed Mar 11, 2017
2 parents ae3ea44 + 18f74bc commit 3ccd4d0
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 26 deletions.
97 changes: 74 additions & 23 deletions src/apulse-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ data_available_for_stream(pa_mainloop_api *a, pa_io_event *ioe, int fd, pa_io_ev
snd_pcm_sframes_t frame_count;
size_t frame_size = pa_frame_size(&s->ss);
char buf[16 * 1024];
const size_t buf_size = pa_find_multiple_of(sizeof(buf), frame_size);
const size_t buf_size = pa_find_multiple_of(sizeof(buf), frame_size, 0);
int paused = g_atomic_int_get(&s->paused);

if (events & (PA_IO_EVENT_INPUT | PA_IO_EVENT_OUTPUT)) {
Expand Down Expand Up @@ -128,8 +128,9 @@ data_available_for_stream(pa_mainloop_api *a, pa_io_event *ioe, int fd, pa_io_ev
} else {
size_t writable_size = pa_stream_writable_size(s);

if (s->write_cb && writable_size > 0)
s->write_cb(s, writable_size, s->write_cb_userdata);
// Ask client for data, but only if we are ready for at least |minreq| bytes.
if (s->write_cb && writable_size >= s->buffer_attr.minreq)
s->write_cb(s, s->buffer_attr.minreq, s->write_cb_userdata);

size_t bytecnt = MIN(buf_size, frame_count * frame_size);
bytecnt = ringbuffer_read(s->rb, buf, bytecnt);
Expand Down Expand Up @@ -286,6 +287,72 @@ pa_stream_cancel_write(pa_stream *p)
return 0;
}

static void
stream_adjust_buffer_attrs(pa_stream *s, const pa_buffer_attr *attr)
{
pa_buffer_attr *ba = &s->buffer_attr;
const size_t frame_size = pa_frame_size(&s->ss);

if (attr) {
*ba = *attr;
} else {
// If client passed NULL, all parameters have default values.
ba->maxlength = (uint32_t)-1;
ba->tlength = (uint32_t)-1;
ba->prebuf = (uint32_t)-1;
ba->minreq = (uint32_t)-1;
ba->fragsize = (uint32_t)-1;
}

// Adjust default values.
// Overall buffer length.
if (ba->maxlength == (uint32_t)-1)
ba->maxlength = 4 * 1024 * 1024;

if (ba->maxlength == 0)
ba->maxlength = frame_size;

// Target length of a buffer.
if (ba->tlength == (uint32_t)-1)
ba->tlength = pa_usec_to_bytes(2 * 1000 * 1000, &s->ss);

if (ba->tlength == 0)
ba->tlength = frame_size;

ba->tlength = MIN(ba->tlength, ba->maxlength);

// Minimum request (playback).
if (ba->minreq == (uint32_t)-1) {
ba->minreq = pa_usec_to_bytes(20 * 1000, &s->ss);
ba->minreq = MIN(ba->minreq, ba->tlength / 4);
}

if (ba->minreq == 0)
ba->minreq = frame_size;

// Fragment size (recording).
if (ba->fragsize == (uint32_t)-1) {
ba->fragsize = pa_usec_to_bytes(20 * 1000, &s->ss);
}

if (ba->fragsize == 0)
ba->fragsize = frame_size;

// Pre-buffering.
if (ba->prebuf == (uint32_t)-1)
ba->prebuf = ba->tlength - ba->minreq;

if (ba->prebuf > ba->tlength - ba->minreq)
ba->prebuf = ba->tlength - ba->minreq;

// Ensure values are all multiple of |frame_size|.
ba->maxlength = pa_find_multiple_of(ba->maxlength, frame_size, 1);
ba->tlength = pa_find_multiple_of(ba->tlength, frame_size, 1);
ba->prebuf = pa_find_multiple_of(ba->prebuf, frame_size, 1);
ba->minreq = pa_find_multiple_of(ba->minreq, frame_size, 1);
ba->fragsize = pa_find_multiple_of(ba->fragsize, frame_size, 1);
}

APULSE_EXPORT
int
pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr,
Expand All @@ -298,15 +365,7 @@ pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *
g_free(s_attr);

s->direction = PA_STREAM_PLAYBACK;
if (attr) {
s->buffer_attr = *attr;
} else {
s->buffer_attr.maxlength = (uint32_t)-1;
s->buffer_attr.tlength = (uint32_t)-1;
s->buffer_attr.prebuf = (uint32_t)-1;
s->buffer_attr.minreq = (uint32_t)-1;
s->buffer_attr.fragsize = (uint32_t)-1;
}
stream_adjust_buffer_attrs(s, attr);

if (do_connect_pcm(s, SND_PCM_STREAM_PLAYBACK) != 0)
goto err;
Expand Down Expand Up @@ -759,7 +818,7 @@ pa_stream_writable_size(pa_stream *s)
if (writable_size < limit)
writable_size = 0;

return pa_find_multiple_of(writable_size, pa_frame_size(&s->ss));
return pa_find_multiple_of(writable_size, pa_frame_size(&s->ss), 0);
}

APULSE_EXPORT
Expand All @@ -769,7 +828,7 @@ pa_stream_readable_size(pa_stream *s)
trace_info_f("F %s s=%p\n", __func__, s);

size_t readable_size = ringbuffer_readable_size(s->rb);
return pa_find_multiple_of(readable_size, pa_frame_size(&s->ss));
return pa_find_multiple_of(readable_size, pa_frame_size(&s->ss), 0);
}

APULSE_EXPORT
Expand Down Expand Up @@ -810,15 +869,7 @@ pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *at
g_free(s_attr);

s->direction = PA_STREAM_RECORD;
if (attr) {
s->buffer_attr = *attr;
} else {
s->buffer_attr.maxlength = (uint32_t)-1;
s->buffer_attr.tlength = (uint32_t)-1;
s->buffer_attr.prebuf = (uint32_t)-1;
s->buffer_attr.minreq = (uint32_t)-1;
s->buffer_attr.fragsize = (uint32_t)-1;
}
stream_adjust_buffer_attrs(s, attr);

if (do_connect_pcm(s, SND_PCM_STREAM_CAPTURE) != 0)
goto err;
Expand Down
8 changes: 6 additions & 2 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,13 @@ pa_sample_format_from_string(const char *str)
}

size_t
pa_find_multiple_of(size_t number, size_t multiple_of)
pa_find_multiple_of(size_t number, size_t multiple_of, int towards_larger_numbers)
{
return number - (number % multiple_of);
if (multiple_of == 0)
return number;

size_t n = towards_larger_numbers ? (number + multiple_of - 1) : number;
return n - (n % multiple_of);
}

void
Expand Down
2 changes: 1 addition & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pa_sample_format_from_string(const char *str);

/// finds largest number that is less or equal than |number| and multiple of |multiple_of|.
size_t
pa_find_multiple_of(size_t number, size_t multiple_of);
pa_find_multiple_of(size_t number, size_t multiple_of, int towards_larger_numbers);

void
pa_apply_volume_multiplier(void *buf, size_t sz, const pa_volume_t volume[PA_CHANNELS_MAX],
Expand Down

0 comments on commit 3ccd4d0

Please sign in to comment.