pulse-server: keep allocate buffer size around

For playback and capture streams we allocate MAXLENGTH (4M) buffers but
for upload streams we must allow space for the total upload stream, which
can be up to the max allowed sample size (16M).

Keep the allocated size for the stream around in a variable so that we
can use it when writing/reading to/from the ringbuffer.

This could later also be extended to use the attr.maxlength variable to
size the buffer (but it's usually 4M anyway). This is more complicated
because we need to grow the buffer size when new attributes are set,
which is probably more complicated than useful.
This commit is contained in:
Wim Taymans 2026-04-30 15:18:56 +02:00
parent 32648b7cc7
commit b7aae374bf
5 changed files with 23 additions and 21 deletions

View file

@ -572,7 +572,8 @@ static int reply_create_playback_stream(struct stream *stream, struct pw_manager
const char *peer_name;
uint64_t lat_usec;
stream->buffer = calloc(1, MAXLENGTH);
stream->bufsize = MAXLENGTH;
stream->buffer = calloc(1, stream->bufsize);
if (stream->buffer == NULL)
return -errno;
@ -731,7 +732,8 @@ static int reply_create_record_stream(struct stream *stream, struct pw_manager_o
uint32_t peer_index;
uint64_t lat_usec;
stream->buffer = calloc(1, MAXLENGTH);
stream->bufsize = MAXLENGTH;
stream->buffer = calloc(1, stream->bufsize);
if (stream->buffer == NULL)
return -errno;
@ -1399,8 +1401,8 @@ do_process_done(struct spa_loop *loop,
return -errno;
spa_ringbuffer_read_data(&stream->ring,
stream->buffer, MAXLENGTH,
index % MAXLENGTH,
stream->buffer, stream->bufsize,
index % stream->bufsize,
msg->data, towrite);
client_queue_message(client, msg);
@ -1472,8 +1474,8 @@ static void stream_process(void *data)
if (avail > 0) {
avail = SPA_MIN((uint32_t)avail, size);
spa_ringbuffer_read_data(&stream->ring,
stream->buffer, MAXLENGTH,
index % MAXLENGTH,
stream->buffer, stream->bufsize,
index % stream->bufsize,
p, avail);
empty = false;
}
@ -1502,8 +1504,8 @@ static void stream_process(void *data)
size = SPA_MIN(size, minreq);
spa_ringbuffer_read_data(&stream->ring,
stream->buffer, MAXLENGTH,
index % MAXLENGTH,
stream->buffer, stream->bufsize,
index % stream->bufsize,
p, size);
index += size;
@ -1539,10 +1541,10 @@ static void stream_process(void *data)
}
spa_ringbuffer_write_data(&stream->ring,
stream->buffer, MAXLENGTH,
index % MAXLENGTH,
stream->buffer, stream->bufsize,
index % stream->bufsize,
SPA_PTROFF(p, offs, void),
SPA_MIN(size, MAXLENGTH));
SPA_MIN(size, stream->bufsize));
index += size;
pd.write_inc = size;
@ -2361,7 +2363,8 @@ static int do_create_upload_stream(struct client *client, uint32_t command, uint
stream->props = props;
stream->buffer = calloc(1, MAXLENGTH);
stream->bufsize = stream->attr.maxlength;
stream->buffer = calloc(1, stream->bufsize);
if (stream->buffer == NULL)
goto error_errno;

View file

@ -100,8 +100,7 @@ static void sample_play_stream_process(void *data)
if (b->requested)
size = SPA_MIN(size, b->requested * p->stride);
spa_ringbuffer_read_data(NULL, s->buffer, MAXLENGTH,
p->offset % MAXLENGTH, d, size);
memcpy(d, s->buffer + p->offset, size);
p->offset += size;

View file

@ -103,7 +103,7 @@ finish:
static void stream_clear_data(struct stream *stream,
uint32_t offset, uint32_t len)
{
uint32_t l0 = SPA_MIN(len, MAXLENGTH - offset), l1 = len - l0;
uint32_t l0 = SPA_MIN(len, stream->bufsize - offset), l1 = len - l0;
sample_spec_silence(&stream->ss, SPA_PTROFF(stream->buffer, offset, void), l0);
if (SPA_UNLIKELY(l1 > 0))
sample_spec_silence(&stream->ss, stream->buffer, l1);
@ -162,7 +162,7 @@ static int handle_memblock(struct client *client, struct message *msg)
* play back old data. FIXME, if the write pointer goes backwards and
* forwards, this might clear valid data. We should probably keep track of
* the highest write pointer and only clear when we go past that one. */
stream_clear_data(stream, index % MAXLENGTH, SPA_MIN(diff, MAXLENGTH));
stream_clear_data(stream, index % stream->bufsize, SPA_MIN(diff, stream->bufsize));
}
index += diff;
@ -181,10 +181,10 @@ static int handle_memblock(struct client *client, struct message *msg)
/* always write data to ringbuffer, we expect the other side
* to recover */
spa_ringbuffer_write_data(&stream->ring,
stream->buffer, MAXLENGTH,
index % MAXLENGTH,
stream->buffer, stream->bufsize,
index % stream->bufsize,
msg->data,
SPA_MIN(msg->length, MAXLENGTH));
SPA_MIN(msg->length, stream->bufsize));
index += msg->length;
spa_ringbuffer_write_update(&stream->ring, index);

View file

@ -163,7 +163,6 @@ void stream_free(struct stream *stream)
pw_work_queue_cancel(impl->work_queue, stream, SPA_ID_INVALID);
if (stream->buffer)
free(stream->buffer);
pw_properties_free(stream->props);

View file

@ -55,6 +55,7 @@ struct stream {
struct spa_io_position *position;
struct spa_ringbuffer ring;
void *buffer;
uint32_t bufsize;
int64_t read_index;
int64_t write_index;