pulse-server: improve under and overrun handling

This commit is contained in:
Wim Taymans 2020-11-09 12:06:44 +01:00
parent 8abb648ec3
commit bd57c1a457

View file

@ -1229,19 +1229,20 @@ do_process_done(struct spa_loop *loop,
send_command_request(stream);
} else {
struct message *msg;
stream->write_index = pd->write_index;
avail = spa_ringbuffer_get_read_index(&stream->ring, &index);
if (avail <= 0) {
/* underrun */
if (!stream->is_underrun) {
stream->is_underrun = true;
send_underflow(stream, index);
}
} else if (avail > (int32_t)stream->attr.maxlength) {
/* overrun */
send_overflow(stream);
/* underrun, can't really happen but if it does we
* do nothing and wait for more data */
pw_log_warn(NAME" %p: underrun", stream);
} else {
struct message *msg;
if (avail > (int32_t)stream->attr.maxlength) {
/* overrun, catch up to latest fragment and send it */
pw_log_warn(NAME" %p: overrun", stream);
avail = stream->attr.fragsize;
index = stream->write_index - avail;
}
msg = message_alloc(client, stream->channel, avail);
if (msg == NULL)
@ -1255,8 +1256,6 @@ do_process_done(struct spa_loop *loop,
stream->read_index = index + avail;
spa_ringbuffer_read_update(&stream->ring, stream->read_index);
stream->is_underrun = false;
send_message(client, msg);
}
}
@ -1289,7 +1288,7 @@ static void stream_process(void *data)
if (stream->direction == PW_DIRECTION_OUTPUT) {
int32_t avail = spa_ringbuffer_get_read_index(&stream->ring, &pd.read_index);
if (avail <= 0) {
/* underrun */
/* underrun, produce a silence buffer */
size = buf->datas[0].maxsize;
memset(p, 0, size);
@ -1299,12 +1298,14 @@ static void stream_process(void *data)
pd.underrun_for = size;
pd.underrun = true;
}
} else if (avail > (int32_t)stream->attr.maxlength) {
/* overrun, handled by other side */
pw_log_warn(NAME" %p: overrun", stream);
size = buf->datas[0].maxsize;
memset(p, 0, size);
} else {
if (avail > (int32_t)stream->attr.maxlength) {
/* overrun, reported by other side, here we skip
* ahead to the oldest data. */
pw_log_warn(NAME" %p: overrun", stream);
pd.read_index += avail - stream->attr.maxlength;
avail = stream->attr.maxlength;
}
size = SPA_MIN(buf->datas[0].maxsize, (uint32_t)avail);
spa_ringbuffer_read_data(&stream->ring,
@ -1324,16 +1325,17 @@ static void stream_process(void *data)
buffer->size = size / stream->frame_size;
} else {
int32_t filled = spa_ringbuffer_get_write_index(&stream->ring, &pd.write_index);
size = buf->datas[0].chunk->size;
if (filled < 0) {
/* underrun */
/* underrun, can't really happen because we never read more
* than what's available on the other side */
pw_log_warn(NAME" %p: underrun", stream);
} else if (filled > (int32_t)stream->attr.maxlength) {
/* overrun */
} else if ((uint32_t)filled + size > stream->attr.maxlength) {
/* overrun, can happen when the other side is not
* reading fast enough. We still write our data into the
* ringbuffer and expect the other side to catch up. */
pw_log_warn(NAME" %p: overrun", stream);
} else {
uint32_t avail = stream->attr.maxlength - filled;
size = SPA_MIN(buf->datas[0].chunk->size, avail);
}
spa_ringbuffer_write_data(&stream->ring,
stream->buffer, stream->attr.maxlength,
pd.write_index % stream->attr.maxlength,
@ -1341,9 +1343,7 @@ static void stream_process(void *data)
size);
pd.write_index += size;
spa_ringbuffer_write_update(&stream->ring,
pd.write_index);
}
spa_ringbuffer_write_update(&stream->ring, pd.write_index);
}
pw_stream_queue_buffer(stream->stream, buffer);
@ -4083,13 +4083,13 @@ static int handle_memblock(struct client *client, struct message *msg)
} else if (filled + msg->length > stream->attr.maxlength) {
/* overrun */
send_overflow(stream);
} else {
}
/* always write data to ringbuffer, we expect the other side
* to recover */
spa_ringbuffer_write_data(&stream->ring,
stream->buffer, stream->attr.maxlength,
index % stream->attr.maxlength,
msg->data, msg->length);
}
stream->write_index = index + msg->length;
spa_ringbuffer_write_update(&stream->ring, stream->write_index);
stream->requested -= msg->length;