mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-19 07:00:10 -05:00
optimize data transport
Remove queue and ringbuffer between nodes. transfer the buffer id directly between the io areas when possible. Let only pinos send push or pull requests for now. Allow polling multiple fds, like how alsa wants it Remove port_id from events.
This commit is contained in:
parent
c8648eaf59
commit
7a9dc2c4fd
18 changed files with 265 additions and 214 deletions
|
|
@ -83,31 +83,58 @@ typedef struct {
|
|||
uint8_t buffer_data[DATAS_SIZE];
|
||||
} PinosLoopImpl;
|
||||
|
||||
static inline uint32_t
|
||||
spa_io_to_epoll (SpaIO mask)
|
||||
{
|
||||
uint32_t events = 0;
|
||||
|
||||
if (mask & SPA_IO_IN)
|
||||
events |= EPOLLIN;
|
||||
if (mask & SPA_IO_OUT)
|
||||
events |= EPOLLOUT;
|
||||
if (mask & SPA_IO_ERR)
|
||||
events |= EPOLLERR;
|
||||
if (mask & SPA_IO_HUP)
|
||||
events |= EPOLLHUP;
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
static inline SpaIO
|
||||
spa_epoll_to_io (uint32_t events)
|
||||
{
|
||||
SpaIO mask = 0;
|
||||
|
||||
if (events & EPOLLIN)
|
||||
mask |= SPA_IO_IN;
|
||||
if (events & EPOLLOUT)
|
||||
mask |= SPA_IO_OUT;
|
||||
if (events & EPOLLHUP)
|
||||
mask |= SPA_IO_HUP;
|
||||
if (events & EPOLLERR)
|
||||
mask |= SPA_IO_ERR;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
loop_add_source (SpaLoop *loop,
|
||||
SpaSource *source)
|
||||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, loop);
|
||||
struct epoll_event ep;
|
||||
|
||||
source->loop = loop;
|
||||
|
||||
if (source->fd != -1) {
|
||||
struct epoll_event ep;
|
||||
|
||||
spa_zero (ep);
|
||||
if (source->mask & SPA_IO_IN)
|
||||
ep.events |= EPOLLIN;
|
||||
if (source->mask & SPA_IO_OUT)
|
||||
ep.events |= EPOLLOUT;
|
||||
if (source->mask & SPA_IO_ERR)
|
||||
ep.events |= EPOLLERR;
|
||||
if (source->mask & SPA_IO_HUP)
|
||||
ep.events |= EPOLLHUP;
|
||||
ep.events = spa_io_to_epoll (source->mask);
|
||||
ep.data.ptr = source;
|
||||
|
||||
if (epoll_ctl (impl->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0)
|
||||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -121,14 +148,7 @@ loop_update_source (SpaSource *source)
|
|||
struct epoll_event ep;
|
||||
|
||||
spa_zero (ep);
|
||||
if (source->mask & SPA_IO_IN)
|
||||
ep.events |= EPOLLIN;
|
||||
if (source->mask & SPA_IO_OUT)
|
||||
ep.events |= EPOLLOUT;
|
||||
if (source->mask & SPA_IO_ERR)
|
||||
ep.events |= EPOLLERR;
|
||||
if (source->mask & SPA_IO_HUP)
|
||||
ep.events |= EPOLLHUP;
|
||||
ep.events = spa_io_to_epoll (source->mask);
|
||||
ep.data.ptr = source;
|
||||
|
||||
if (epoll_ctl (impl->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep) < 0)
|
||||
|
|
@ -240,10 +260,6 @@ loop_enter (SpaLoopControl *ctrl)
|
|||
{
|
||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
|
||||
impl->thread = pthread_self();
|
||||
if (impl->event == NULL)
|
||||
impl->event = spa_loop_utils_add_event (&impl->utils,
|
||||
event_func,
|
||||
impl);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -275,20 +291,19 @@ loop_iterate (SpaLoopControl *ctrl,
|
|||
return SPA_RESULT_ERRNO;
|
||||
}
|
||||
|
||||
/* first we set all the rmasks, then call the callbacks. The reason is that
|
||||
* some callback might also want to look at other sources it manages and
|
||||
* can then reset the rmask to suppress the callback */
|
||||
for (i = 0; i < nfds; i++) {
|
||||
SpaSource *source = ep[i].data.ptr;
|
||||
|
||||
source->rmask = 0;
|
||||
if (ep[i].events & EPOLLIN)
|
||||
source->rmask |= SPA_IO_IN;
|
||||
if (ep[i].events & EPOLLOUT)
|
||||
source->rmask |= SPA_IO_OUT;
|
||||
if (ep[i].events & EPOLLHUP)
|
||||
source->rmask |= SPA_IO_HUP;
|
||||
if (ep[i].events & EPOLLERR)
|
||||
source->rmask |= SPA_IO_ERR;
|
||||
|
||||
source->func (source);
|
||||
source->rmask = spa_epoll_to_io (ep[i].events);
|
||||
}
|
||||
for (i = 0; i < nfds; i++) {
|
||||
SpaSource *source = ep[i].data.ptr;
|
||||
if (source->rmask) {
|
||||
source->func (source);
|
||||
source->rmask = 0;
|
||||
}
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -610,6 +625,10 @@ pinos_loop_new (void)
|
|||
|
||||
spa_ringbuffer_init (&impl->buffer, DATAS_SIZE);
|
||||
|
||||
impl->event = spa_loop_utils_add_event (&impl->utils,
|
||||
event_func,
|
||||
impl);
|
||||
|
||||
return this;
|
||||
|
||||
no_epoll:
|
||||
|
|
@ -628,6 +647,8 @@ pinos_loop_destroy (PinosLoop *loop)
|
|||
spa_list_for_each_safe (source, tmp, &impl->source_list, link)
|
||||
loop_destroy_source (&source->source);
|
||||
|
||||
pinos_loop_destroy_source (loop, impl->event);
|
||||
|
||||
close (impl->epoll_fd);
|
||||
free (impl);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ typedef struct {
|
|||
bool used;
|
||||
void *buf_ptr;
|
||||
SpaBuffer *buf;
|
||||
SpaData *datas;
|
||||
} BufferId;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -310,29 +309,35 @@ add_port_update (PinosStream *stream, uint32_t change_mask, bool flush)
|
|||
static inline void
|
||||
send_need_input (PinosStream *stream)
|
||||
{
|
||||
#if 0
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
SpaNodeEventNeedInput ni;
|
||||
uint8_t cmd = 0;
|
||||
uint64_t cmd = 1;
|
||||
|
||||
pinos_log_debug ("stream %p: need input", stream);
|
||||
|
||||
ni.event.type = SPA_NODE_EVENT_TYPE_NEED_INPUT;
|
||||
ni.event.size = sizeof (ni);
|
||||
ni.port_id = 0;
|
||||
pinos_transport_add_event (impl->trans, &ni.event);
|
||||
write (impl->rtfd, &cmd, 1);
|
||||
write (impl->rtfd, &cmd, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
send_have_output (PinosStream *stream)
|
||||
{
|
||||
#if 0
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
SpaNodeEventHaveOutput ho;
|
||||
uint8_t cmd = 0;
|
||||
uint64_t cmd = 1;
|
||||
|
||||
pinos_log_debug ("stream %p: have output", stream);
|
||||
|
||||
ho.event.type = SPA_NODE_EVENT_TYPE_HAVE_OUTPUT;
|
||||
ho.event.size = sizeof (ho);
|
||||
ho.port_id = 0;
|
||||
pinos_transport_add_event (impl->trans, &ho.event);
|
||||
write (impl->rtfd, &cmd, 1);
|
||||
write (impl->rtfd, &cmd, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -442,6 +447,8 @@ handle_rtnode_event (PinosStream *stream,
|
|||
{
|
||||
int i;
|
||||
|
||||
//pinos_log_debug ("stream %p: have output", stream);
|
||||
|
||||
for (i = 0; i < impl->trans->area->n_inputs; i++) {
|
||||
SpaPortInput *input = &impl->trans->inputs[i];
|
||||
|
||||
|
|
@ -456,6 +463,7 @@ handle_rtnode_event (PinosStream *stream,
|
|||
}
|
||||
|
||||
case SPA_NODE_EVENT_TYPE_NEED_INPUT:
|
||||
//pinos_log_debug ("stream %p: need input", stream);
|
||||
pinos_signal_emit (&stream->need_buffer, stream);
|
||||
break;
|
||||
|
||||
|
|
@ -469,7 +477,7 @@ handle_rtnode_event (PinosStream *stream,
|
|||
if (impl->direction != SPA_DIRECTION_OUTPUT)
|
||||
break;
|
||||
|
||||
if ((bid = find_buffer (stream, p->buffer_id))) {
|
||||
if ((bid = find_buffer (stream, p->buffer_id)) && bid->used) {
|
||||
bid->used = false;
|
||||
pinos_signal_emit (&stream->new_buffer, stream, p->buffer_id);
|
||||
}
|
||||
|
|
@ -481,6 +489,17 @@ handle_rtnode_event (PinosStream *stream,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unhandle_socket (PinosStream *stream)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
|
||||
if (impl->rtsocket_source) {
|
||||
pinos_loop_destroy_source (stream->context->loop, impl->rtsocket_source);
|
||||
impl->rtsocket_source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_rtsocket_condition (SpaSource *source,
|
||||
int fd,
|
||||
|
|
@ -492,13 +511,15 @@ on_rtsocket_condition (SpaSource *source,
|
|||
|
||||
if (mask & (SPA_IO_ERR | SPA_IO_HUP)) {
|
||||
pinos_log_warn ("got error");
|
||||
unhandle_socket (stream);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask & SPA_IO_IN) {
|
||||
SpaNodeEvent event;
|
||||
uint8_t cmd;
|
||||
uint64_t cmd;
|
||||
|
||||
read (impl->rtfd, &cmd, 1);
|
||||
read (impl->rtfd, &cmd, 8);
|
||||
|
||||
while (pinos_transport_next_event (impl->trans, &event) == SPA_RESULT_OK) {
|
||||
SpaNodeEvent *ev = alloca (event.size);
|
||||
|
|
@ -535,17 +556,6 @@ handle_socket (PinosStream *stream, int rtfd)
|
|||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
unhandle_socket (PinosStream *stream)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
|
||||
if (impl->rtsocket_source) {
|
||||
pinos_loop_destroy_source (stream->context->loop, impl->rtsocket_source);
|
||||
impl->rtsocket_source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_node_event (PinosStream *stream,
|
||||
SpaNodeEvent *event)
|
||||
|
|
@ -724,6 +734,7 @@ stream_dispatch_func (void *object,
|
|||
}
|
||||
len = pinos_array_get_len (&impl->buffer_ids, BufferId);
|
||||
bid = pinos_array_add (&impl->buffer_ids, sizeof (BufferId));
|
||||
bid->used = false;
|
||||
|
||||
b = p->buffers[i].buffer;
|
||||
|
||||
|
|
@ -1052,14 +1063,14 @@ pinos_stream_recycle_buffer (PinosStream *stream,
|
|||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
SpaNodeEventReuseBuffer rb;
|
||||
uint8_t cmd = 0;
|
||||
uint64_t cmd = 1;
|
||||
|
||||
rb.event.type = SPA_NODE_EVENT_TYPE_REUSE_BUFFER;
|
||||
rb.event.size = sizeof (rb);
|
||||
rb.port_id = impl->port_id;
|
||||
rb.buffer_id = id;
|
||||
pinos_transport_add_event (impl->trans, &rb.event);
|
||||
write (impl->rtfd, &cmd, 1);
|
||||
write (impl->rtfd, &cmd, 8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1107,11 +1118,18 @@ pinos_stream_send_buffer (PinosStream *stream,
|
|||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
BufferId *bid;
|
||||
|
||||
if ((bid = find_buffer (stream, id))) {
|
||||
if (impl->trans->outputs[0].buffer_id != SPA_ID_INVALID) {
|
||||
pinos_log_debug ("can't send %u, pending buffer %u", id, impl->trans->outputs[0].buffer_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((bid = find_buffer (stream, id)) && !bid->used) {
|
||||
bid->used = true;
|
||||
impl->trans->outputs[0].buffer_id = id;
|
||||
impl->trans->outputs[0].status = SPA_RESULT_OK;
|
||||
send_have_output (stream);
|
||||
} else {
|
||||
pinos_log_debug ("stream %p: output %u was used", stream, id);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -60,14 +60,27 @@ static void
|
|||
transport_setup_area (void *p, PinosTransport *trans)
|
||||
{
|
||||
PinosTransportArea *a;
|
||||
int i;
|
||||
|
||||
trans->area = a = p;
|
||||
p = SPA_MEMBER (p, sizeof (PinosTransportArea), SpaPortInput);
|
||||
|
||||
trans->inputs = p;
|
||||
for (i = 0; i < a->max_inputs; i++) {
|
||||
trans->inputs[i].state = SPA_PORT_STATE_FLAG_NONE;
|
||||
trans->inputs[i].flags = SPA_PORT_INPUT_FLAG_NONE;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->inputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
p = SPA_MEMBER (p, a->max_inputs * sizeof (SpaPortInput), void);
|
||||
|
||||
trans->outputs = p;
|
||||
for (i = 0; i < a->max_outputs; i++) {
|
||||
trans->outputs[i].state = SPA_PORT_STATE_FLAG_NONE;
|
||||
trans->outputs[i].flags = SPA_PORT_OUTPUT_FLAG_NONE;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->outputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
p = SPA_MEMBER (p, a->max_outputs * sizeof (SpaPortOutput), void);
|
||||
|
||||
trans->input_buffer = p;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue