Work on event loop

Make a new epoll based event loop and use it for the data tranport.
Simplify the spa event api a little and rename to SpaLoop
This commit is contained in:
Wim Taymans 2016-11-18 17:46:01 +01:00
parent 0d2fa5ebc8
commit ae93f15965
33 changed files with 1286 additions and 954 deletions

View file

@ -23,10 +23,10 @@
#include <string.h>
#include <stdio.h>
#include <sys/timerfd.h>
#include <poll.h>
#include <spa/id-map.h>
#include <spa/log.h>
#include <spa/loop.h>
#include <spa/node.h>
#include <spa/list.h>
#include <spa/video/format.h>
@ -74,15 +74,15 @@ struct _SpaVideoTestSrc {
URI uri;
SpaIDMap *map;
SpaLog *log;
SpaPoll *data_loop;
SpaLoop *data_loop;
SpaVideoTestSrcProps props[2];
SpaNodeEventCallback event_cb;
void *user_data;
SpaPollItem timer;
SpaPollFd fds[1];
SpaSource timer_source;
bool timer_enabled;
struct itimerspec timerspec;
SpaPortInfo info;
@ -205,18 +205,18 @@ fill_buffer (SpaVideoTestSrc *this, VTSBuffer *b)
return SPA_RESULT_OK;
}
static SpaResult update_poll_enabled (SpaVideoTestSrc *this, bool enabled);
static SpaResult update_loop_enabled (SpaVideoTestSrc *this, bool enabled);
static int
videotestsrc_on_output (SpaPollNotifyData *data)
static void
videotestsrc_on_output (SpaSource *source)
{
SpaVideoTestSrc *this = data->user_data;
SpaVideoTestSrc *this = source->data;
VTSBuffer *b;
if (spa_list_is_empty (&this->empty)) {
if (!this->props[1].live)
update_poll_enabled (this, false);
return 0;
update_loop_enabled (this, false);
return;
}
b = spa_list_first (&this->empty, VTSBuffer, list);
spa_list_remove (&b->list);
@ -235,19 +235,17 @@ videotestsrc_on_output (SpaPollNotifyData *data)
if (this->props[1].live) {
uint64_t expirations, next_time;
if (read (this->fds[0].fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t))
if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t))
perror ("read timerfd");
next_time = this->start_time + this->elapsed_time;
this->timerspec.it_value.tv_sec = next_time / SPA_NSEC_PER_SEC;
this->timerspec.it_value.tv_nsec = next_time % SPA_NSEC_PER_SEC;
timerfd_settime (this->fds[0].fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL);
timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL);
}
spa_list_insert (this->ready.prev, &b->list);
send_have_output (this);
return 0;
}
static void
@ -257,10 +255,15 @@ update_state (SpaVideoTestSrc *this, SpaNodeState state)
}
static SpaResult
update_poll_enabled (SpaVideoTestSrc *this, bool enabled)
update_loop_enabled (SpaVideoTestSrc *this, bool enabled)
{
if (this->event_cb && this->timer.enabled != enabled) {
this->timer.enabled = enabled;
if (this->event_cb && this->timer_enabled != enabled) {
this->timer_enabled = enabled;
if (enabled)
this->timer_source.mask = SPA_IO_IN;
else
this->timer_source.mask = 0;
if (this->props[1].live) {
if (enabled) {
uint64_t next_time = this->start_time + this->elapsed_time;
@ -271,18 +274,9 @@ update_poll_enabled (SpaVideoTestSrc *this, bool enabled)
this->timerspec.it_value.tv_sec = 0;
this->timerspec.it_value.tv_nsec = 0;
}
timerfd_settime (this->fds[0].fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL);
this->timer.fds = this->fds;
this->timer.n_fds = 1;
this->timer.idle_cb = NULL;
this->timer.after_cb = videotestsrc_on_output;
} else {
this->timer.fds = NULL;
this->timer.n_fds = 0;
this->timer.idle_cb = videotestsrc_on_output;
this->timer.after_cb = NULL;
timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL);
}
spa_poll_update_item (this->data_loop, &this->timer);
spa_loop_update_source (this->data_loop, &this->timer_source);
}
return SPA_RESULT_OK;
}
@ -324,7 +318,7 @@ spa_videotestsrc_node_send_command (SpaNode *node,
this->elapsed_time = 0;
this->started = true;
update_poll_enabled (this, true);
update_loop_enabled (this, true);
update_state (this, SPA_NODE_STATE_STREAMING);
break;
}
@ -340,7 +334,7 @@ spa_videotestsrc_node_send_command (SpaNode *node,
return SPA_RESULT_OK;
this->started = false;
update_poll_enabled (this, false);
update_loop_enabled (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
break;
}
@ -365,15 +359,14 @@ spa_videotestsrc_node_set_event_callback (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
if (event_cb == NULL && this->event_cb) {
spa_poll_remove_item (this->data_loop, &this->timer);
}
if (event_cb == NULL && this->event_cb)
spa_loop_remove_source (this->data_loop, &this->timer_source);
this->event_cb = event_cb;
this->user_data = user_data;
if (this->event_cb) {
spa_poll_add_item (this->data_loop, &this->timer);
spa_loop_add_source (this->data_loop, &this->timer_source);
}
return SPA_RESULT_OK;
}
@ -748,7 +741,7 @@ spa_videotestsrc_node_port_reuse_buffer (SpaNode *node,
spa_list_insert (this->empty.prev, &b->list);
if (!this->props[1].live)
update_poll_enabled (this, true);
update_loop_enabled (this, true);
return SPA_RESULT_OK;
}
@ -910,7 +903,7 @@ videotestsrc_clear (SpaHandle *handle)
this = (SpaVideoTestSrc *) handle;
close (this->fds[0].fd);
close (this->timer_source.fd);
return SPA_RESULT_OK;
}
@ -938,7 +931,7 @@ videotestsrc_init (const SpaHandleFactory *factory,
this->map = support[i].data;
else if (strcmp (support[i].uri, SPA_LOG_URI) == 0)
this->log = support[i].data;
else if (strcmp (support[i].uri, SPA_POLL__DataLoop) == 0)
else if (strcmp (support[i].uri, SPA_LOOP__DataLoop) == 0)
this->data_loop = support[i].data;
}
if (this->map == NULL) {
@ -957,21 +950,16 @@ videotestsrc_init (const SpaHandleFactory *factory,
spa_list_init (&this->empty);
spa_list_init (&this->ready);
this->fds[0].fd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
this->fds[0].events = POLLIN | POLLPRI | POLLERR;
this->fds[0].revents = 0;
this->timer_source.func = videotestsrc_on_output;
this->timer_source.data = this;
this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
this->timer_source.mask = SPA_IO_IN;
this->timer_source.rmask = 0;
this->timerspec.it_value.tv_sec = 0;
this->timerspec.it_value.tv_nsec = 0;
this->timerspec.it_interval.tv_sec = 0;
this->timerspec.it_interval.tv_nsec = 0;
this->timer.id = 0;
this->timer.enabled = false;
this->timer.idle_cb = NULL;
this->timer.before_cb = NULL;
this->timer.after_cb = NULL;
this->timer.user_data = this;
this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
if (this->props[1].live)