buffer: don't use ringbuffer in chunk

We can't use a ringbuffer on the chunk because it implies the
consumer would write to it to update the read position, which we
can't do because the chunk is read-only and might even be shared.
Go back to offset/size pairs, which can sortof do the same thing
if we want later when we keep a non-shared read pointer in the
consumer.
Keep alsa timestamp around and filled state for future.
mmap the input port meta/data/chunk as read-only.
Only do clock update requests when asked.
This commit is contained in:
Wim Taymans 2017-11-21 12:30:15 +01:00
parent 2ad722b579
commit 4288a634f4
25 changed files with 165 additions and 126 deletions

View file

@ -364,8 +364,8 @@ static int impl_node_process_output(struct spa_node *node)
int16_t *dst;
struct spa_port_io *io = d->io;
uint32_t maxsize, index = 0;
struct spa_ringbuffer *rb;
uint32_t filled, offset;
struct spa_data *od;
if (io->buffer_id < d->n_buffers) {
reuse_buffer(d, io->buffer_id);
@ -378,10 +378,12 @@ static int impl_node_process_output(struct spa_node *node)
b = spa_list_first(&d->empty, struct buffer, link);
spa_list_remove(&b->link);
maxsize = b->buffer->datas[0].maxsize;
rb = &b->buffer->datas[0].chunk->area;
od = b->buffer->datas;
filled = spa_ringbuffer_get_write_index(rb, &index);
maxsize = od[0].maxsize;
filled = 0;
index = 0;
avail = maxsize - filled;
offset = index % maxsize;
@ -404,7 +406,9 @@ static int impl_node_process_output(struct spa_node *node)
*dst++ = val;
}
spa_ringbuffer_write_update(rb, index + avail);
od[0].chunk->offset = 0;
od[0].chunk->size = avail;
od[0].chunk->stride = 0;
io->buffer_id = b->buffer->id;
io->status = SPA_STATUS_HAVE_BUFFER;

View file

@ -526,8 +526,8 @@ do_send_buffer (GstPipeWireSink *pwsink)
for (i = 0; i < data->buf->n_datas; i++) {
struct spa_data *d = &data->buf->datas[i];
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
d->chunk->area.readindex = mem->offset - data->offset;
d->chunk->area.writeindex = d->chunk->area.readindex + mem->size;
d->chunk->offset = mem->offset - data->offset;
d->chunk->size = mem->size;
}
if (!(res = pw_stream_send_buffer (pwsink->stream, data->id))) {

View file

@ -464,11 +464,9 @@ on_new_buffer (void *_data,
}
for (i = 0; i < data->buf->n_datas; i++) {
struct spa_data *d = &data->buf->datas[i];
uint32_t index;
GstMemory *mem = gst_buffer_peek_memory (buf, i);
mem->size = spa_ringbuffer_get_read_index(&d->chunk->area, &index);
mem->offset = index % d->maxsize;
spa_ringbuffer_set_avail(&d->chunk->area, 0);
mem->offset = SPA_MIN(d->chunk->offset, d->maxsize);
mem->size = SPA_MIN(d->chunk->size, d->maxsize - mem->offset);
}
if (pwsrc->always_copy)
@ -663,7 +661,7 @@ gst_pipewire_src_negotiate (GstBaseSrc * basesrc)
pw_stream_connect (pwsrc->stream,
PW_DIRECTION_INPUT,
pwsrc->path,
PW_STREAM_FLAG_AUTOCONNECT,
PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_CLOCK_UPDATE,
(const struct spa_pod **)possible->pdata,
possible->len);
g_ptr_array_free (possible, TRUE);

View file

@ -21,6 +21,7 @@
#include <errno.h>
#include <sys/mman.h>
#include <spa/utils/ringbuffer.h>
#include <pipewire/log.h>
#include <extensions/client-node.h>

View file

@ -305,7 +305,9 @@ static int driver_process_output(struct spa_node *node)
in_io->status = SPA_STATUS_NEED_BUFFER;
}
spa_ringbuffer_set_avail(&out->outbuf->datas[0].chunk->area, ctrl->buffer_size * sizeof(int16_t) * 2);
out->outbuf->datas[0].chunk->offset = 0;
out->outbuf->datas[0].chunk->size = ctrl->buffer_size * sizeof(int16_t) * 2;
out->outbuf->datas[0].chunk->stride = 0;
spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, push);
gn->ready[SPA_DIRECTION_INPUT] = gn->required[SPA_DIRECTION_OUTPUT] = 0;

View file

@ -305,7 +305,8 @@ static struct spa_pod *find_param(struct spa_pod **params, int n_params, uint32_
* || | ... <n_metas> |
* || +------------------------------+
* +->| struct spa_chunk | memory for n_datas chunks
* | | struct spa_ringbuffer area |
* | | uint32_t offset |
* | | uint32_t size |
* | | int32_t stride |
* | | ... <n_datas> chunks |
* | +------------------------------+
@ -438,7 +439,8 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
d->mapoffset = SPA_PTRDIFF(ddp, mem->ptr);
d->maxsize = data_sizes[j];
d->data = SPA_MEMBER(mem->ptr, d->mapoffset, void);
spa_ringbuffer_set_avail(&d->chunk->area, 0);
d->chunk->offset = 0;
d->chunk->size = 0;
d->chunk->stride = data_strides[j];
ddp += data_sizes[j];
} else {

View file

@ -955,8 +955,7 @@ client_node_port_use_buffers(void *object,
if (mid->ptr == NULL) {
mid->ptr =
mmap(NULL, mid->size + mid->offset, prot, MAP_SHARED,
mid->fd, 0);
mmap(NULL, mid->size + mid->offset, prot, MAP_SHARED, mid->fd, 0);
if (mid->ptr == MAP_FAILED) {
mid->ptr = NULL;
pw_log_warn("Failed to mmap memory %d %p: %s", mid->size, mid,

View file

@ -661,10 +661,12 @@ static void handle_socket(struct pw_stream *stream, int rtreadfd, int rtwritefd)
SPA_IO_ERR | SPA_IO_HUP,
true, on_rtsocket_condition, stream);
impl->timeout_source = pw_loop_add_timer(stream->remote->core->main_loop, on_timeout, stream);
interval.tv_sec = 0;
interval.tv_nsec = 100000000;
pw_loop_update_timer(stream->remote->core->main_loop, impl->timeout_source, NULL, &interval, false);
if (impl->flags & PW_STREAM_FLAG_CLOCK_UPDATE) {
impl->timeout_source = pw_loop_add_timer(stream->remote->core->main_loop, on_timeout, stream);
interval.tv_sec = 0;
interval.tv_nsec = 100000000;
pw_loop_update_timer(stream->remote->core->main_loop, impl->timeout_source, NULL, &interval, false);
}
return;
}
@ -830,6 +832,9 @@ client_node_port_use_buffers(void *data,
struct buffer_id *bid;
uint32_t i, j, len;
struct spa_buffer *b;
int prot;
prot = PROT_READ | (direction == SPA_DIRECTION_OUTPUT ? PROT_WRITE : 0);
/* clear previous buffers */
clear_buffers(stream);
@ -845,8 +850,7 @@ client_node_port_use_buffers(void *data,
if (mid->ptr == NULL) {
mid->ptr =
mmap(NULL, mid->size + mid->offset, PROT_READ | PROT_WRITE, MAP_SHARED,
mid->fd, 0);
mmap(NULL, mid->size + mid->offset, prot, MAP_SHARED, mid->fd, 0);
if (mid->ptr == MAP_FAILED) {
mid->ptr = NULL;
pw_log_warn("Failed to mmap memory %d %p: %s", mid->size, mid,