More work on implementing remote protocol

Rework things so that we negotiate buffer pools beforehand and only pass
buffer ids around We can then remove the refcount of buffers, events and
commands.
More work on buffer reuse
Use the node state changes to trigger the next step in the configuration
sequence.
Move most of the client-node to a plugin
Do buffer allocation in the port link.
This commit is contained in:
Wim Taymans 2016-08-02 16:34:44 +02:00
parent 05829f33e6
commit 3ace7e9648
36 changed files with 1780 additions and 1450 deletions

View file

@ -228,13 +228,13 @@ spa_v4l2_source_node_send_command (SpaNode *node,
if (this->event_cb) {
SpaEvent event;
SpaEventStateChange sc;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_STARTED;
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
event.port_id = -1;
event.data = NULL;
event.size = 0;
event.data = ≻
event.size = sizeof (sc);
sc.state = SPA_NODE_STATE_STREAMING;
this->event_cb (node, &event, this->user_data);
}
@ -244,13 +244,13 @@ spa_v4l2_source_node_send_command (SpaNode *node,
if (this->event_cb) {
SpaEvent event;
SpaEventStateChange sc;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_STOPPED;
event.type = SPA_EVENT_TYPE_STATE_CHANGE;
event.port_id = -1;
event.data = NULL;
event.size = 0;
event.data = ≻
event.size = sizeof (sc);
sc.state = SPA_NODE_STATE_PAUSED;
this->event_cb (node, &event, this->user_data);
}
@ -496,26 +496,6 @@ spa_v4l2_source_node_port_set_props (SpaNode *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static SpaResult
spa_v4l2_source_node_port_get_status (SpaNode *node,
uint32_t port_id,
const SpaPortStatus **status)
{
SpaV4l2Source *this;
if (node == NULL || node->handle == NULL || status == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaV4l2Source *) node->handle;
if (port_id != 0)
return SPA_RESULT_INVALID_PORT;
*status = &this->state[port_id].status;
return SPA_RESULT_OK;
}
static SpaResult
spa_v4l2_source_node_port_use_buffers (SpaNode *node,
uint32_t port_id,
@ -560,6 +540,47 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node,
return SPA_RESULT_OK;
}
static SpaResult
spa_v4l2_source_node_port_reuse_buffer (SpaNode *node,
uint32_t port_id,
uint32_t buffer_id,
off_t offset,
size_t size)
{
SpaV4l2Source *this;
if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaV4l2Source *) node->handle;
if (port_id != 0)
return SPA_RESULT_INVALID_PORT;
spa_v4l2_buffer_recycle (this, buffer_id);
return SPA_RESULT_OK;
}
static SpaResult
spa_v4l2_source_node_port_get_status (SpaNode *node,
uint32_t port_id,
const SpaPortStatus **status)
{
SpaV4l2Source *this;
if (node == NULL || node->handle == NULL || status == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaV4l2Source *) node->handle;
if (port_id != 0)
return SPA_RESULT_INVALID_PORT;
*status = &this->state[port_id].status;
return SPA_RESULT_OK;
}
static SpaResult
spa_v4l2_source_node_port_push_input (SpaNode *node,
@ -584,7 +605,6 @@ spa_v4l2_source_node_port_pull_output (SpaNode *node,
this = (SpaV4l2Source *) node->handle;
for (i = 0; i < n_info; i++) {
V4l2Buffer *b;
@ -612,7 +632,7 @@ spa_v4l2_source_node_port_pull_output (SpaNode *node,
b->outstanding = true;
info[i].id = b->buffer.id;
info[i].buffer_id = b->buffer.id;
info[i].status = SPA_RESULT_OK;
}
if (have_error)
@ -649,6 +669,7 @@ static const SpaNode v4l2source_node = {
spa_v4l2_source_node_port_set_props,
spa_v4l2_source_node_port_use_buffers,
spa_v4l2_source_node_port_alloc_buffers,
spa_v4l2_source_node_port_reuse_buffer,
spa_v4l2_source_node_port_get_status,
spa_v4l2_source_node_port_push_input,
spa_v4l2_source_node_port_pull_output,

View file

@ -437,7 +437,7 @@ spa_v4l2_close (SpaV4l2Source *this)
return 0;
}
static int
static SpaResult
mmap_read (SpaV4l2Source *this)
{
SpaV4l2State *state = &this->state[0];
@ -455,7 +455,7 @@ mmap_read (SpaV4l2Source *this)
case EIO:
default:
perror ("VIDIOC_DQBUF");
return -1;
return SPA_RESULT_ERROR;
}
}
@ -464,7 +464,7 @@ mmap_read (SpaV4l2Source *this)
state->ready = b;
state->ready_count++;
return 0;
return SPA_RESULT_OK;
}
static int
@ -473,10 +473,9 @@ v4l2_on_fd_events (SpaPollNotifyData *data)
SpaV4l2Source *this = data->user_data;
SpaEvent event;
mmap_read (this);
if (mmap_read (this) < 0)
return 0;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_CAN_PULL_OUTPUT;
event.port_id = 0;
event.size = 0;
@ -487,14 +486,11 @@ v4l2_on_fd_events (SpaPollNotifyData *data)
}
static void
v4l2_buffer_recycle (void *data)
spa_v4l2_buffer_recycle (SpaV4l2Source *this, uint32_t buffer_id)
{
SpaBuffer *buf = data;
SpaV4l2Source *this = buf->user_data;
SpaV4l2State *state = &this->state[0];
V4l2Buffer *b = &state->buffers[buf->id];
V4l2Buffer *b = &state->buffers[buffer_id];
b->imported->refcount = 1;
b->outstanding = false;
if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) {
@ -502,7 +498,7 @@ v4l2_buffer_recycle (void *data)
}
}
static int
static SpaResult
spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffers)
{
SpaV4l2State *state = &this->state[0];
@ -518,12 +514,12 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu
if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
perror ("VIDIOC_REQBUFS");
return -1;
return SPA_RESULT_ERROR;
}
fprintf (stderr, "got %d buffers\n", reqbuf.count);
if (reqbuf.count < 2) {
fprintf (stderr, "can't allocate enough buffers\n");
return -1;
return SPA_RESULT_ERROR;
}
state->reqbuf = reqbuf;
@ -532,14 +528,9 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu
b = &state->buffers[i];
buffers[i]->notify = v4l2_buffer_recycle;
buffers[i]->user_data = this;
fprintf (stderr, "import buffer %p\n", buffers[i]);
b->source = this;
b->buffer.refcount = 0;
b->buffer.notify = v4l2_buffer_recycle;
b->buffer.id = buffers[i]->id;
b->buffer.size = buffers[i]->size;
b->buffer.n_metas = buffers[i]->n_metas;
@ -556,14 +547,14 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu
b->v4l2_buffer.m.userptr = (unsigned long) b->buffer.datas[0].ptr;
b->v4l2_buffer.length = b->buffer.datas[0].size;
v4l2_buffer_recycle (buffers[i]);
spa_v4l2_buffer_recycle (this, buffers[i]->id);
}
state->have_buffers = true;
return 0;
return SPA_RESULT_OK;
}
static int
static SpaResult
mmap_init (SpaV4l2Source *this,
SpaAllocParam **params,
unsigned int n_params,
@ -583,7 +574,7 @@ mmap_init (SpaV4l2Source *this,
if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
perror ("VIDIOC_REQBUFS");
return -1;
return SPA_RESULT_ERROR;
}
fprintf (stderr, "got %d buffers\n", reqbuf.count);
@ -591,7 +582,7 @@ mmap_init (SpaV4l2Source *this,
if (reqbuf.count < 2) {
fprintf (stderr, "can't allocate enough buffers\n");
return -1;
return SPA_RESULT_ERROR;
}
if (state->export_buf)
fprintf (stderr, "using EXPBUF\n");
@ -609,7 +600,7 @@ mmap_init (SpaV4l2Source *this,
if (xioctl (state->fd, VIDIOC_QUERYBUF, &buf) < 0) {
perror ("VIDIOC_QUERYBUF");
return -1;
return SPA_RESULT_ERROR;
}
b = &state->buffers[i];
@ -617,9 +608,6 @@ mmap_init (SpaV4l2Source *this,
buffers[i] = &b->buffer;
b->source = this;
b->buffer.refcount = 0;
b->buffer.notify = v4l2_buffer_recycle;
b->buffer.user_data = this;
b->buffer.id = i;
b->buffer.size = buf.length;
b->buffer.n_metas = 1;
@ -679,47 +667,49 @@ mmap_init (SpaV4l2Source *this,
b->v4l2_buffer.memory = state->memtype;
b->v4l2_buffer.index = i;
v4l2_buffer_recycle (b);
spa_v4l2_buffer_recycle (this, i);
}
state->have_buffers = true;
return 0;
return SPA_RESULT_OK;
}
static int
static SpaResult
userptr_init (SpaV4l2Source *this)
{
return -1;
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
static SpaResult
read_init (SpaV4l2Source *this)
{
return -1;
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
static SpaResult
spa_v4l2_alloc_buffers (SpaV4l2Source *this,
SpaAllocParam **params,
unsigned int n_params,
SpaBuffer **buffers,
unsigned int *n_buffers)
{
SpaResult res;
SpaV4l2State *state = &this->state[0];
if (state->cap.capabilities & V4L2_CAP_STREAMING) {
if (mmap_init (this, params, n_params, buffers, n_buffers) < 0)
if (userptr_init (this) < 0)
return -1;
if ((res = mmap_init (this, params, n_params, buffers, n_buffers)) < 0)
if ((res = userptr_init (this)) < 0)
return res;
} else if (state->cap.capabilities & V4L2_CAP_READWRITE) {
if (read_init (this) < 0)
return -1;
if ((res = read_init (this)) < 0)
return res;
} else
return -1;
return 0;
return SPA_RESULT_ERROR;
return SPA_RESULT_OK;
}
static int
static SpaResult
spa_v4l2_start (SpaV4l2Source *this)
{
SpaV4l2State *state = &this->state[0];
@ -727,14 +717,11 @@ spa_v4l2_start (SpaV4l2Source *this)
SpaEvent event;
if (spa_v4l2_open (this) < 0)
return -1;
return SPA_RESULT_ERROR;
if (!state->have_buffers)
return -1;
return SPA_RESULT_NO_BUFFERS;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_ADD_POLL;
event.port_id = 0;
event.data = &state->poll;
@ -756,12 +743,12 @@ spa_v4l2_start (SpaV4l2Source *this)
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl (state->fd, VIDIOC_STREAMON, &type) < 0) {
perror ("VIDIOC_STREAMON");
return -1;
return SPA_RESULT_ERROR;
}
return 0;
return SPA_RESULT_OK;
}
static int
static SpaResult
spa_v4l2_stop (SpaV4l2Source *this)
{
SpaV4l2State *state = &this->state[0];
@ -769,10 +756,13 @@ spa_v4l2_stop (SpaV4l2Source *this)
SpaEvent event;
int i;
if (!state->opened)
return SPA_RESULT_OK;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl (state->fd, VIDIOC_STREAMOFF, &type) < 0) {
perror ("VIDIOC_STREAMOFF");
return -1;
return SPA_RESULT_ERROR;
}
for (i = 0; i < state->reqbuf.count; i++) {
@ -781,7 +771,7 @@ spa_v4l2_stop (SpaV4l2Source *this)
b = &state->buffers[i];
if (b->outstanding) {
fprintf (stderr, "queueing outstanding buffer %p\n", b);
v4l2_buffer_recycle (b);
spa_v4l2_buffer_recycle (this, i);
}
if (state->export_buf) {
close (b->dmafd);
@ -791,8 +781,6 @@ spa_v4l2_stop (SpaV4l2Source *this)
}
state->have_buffers = false;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_REMOVE_POLL;
event.port_id = 0;
event.data = &state->poll;
@ -801,5 +789,5 @@ spa_v4l2_stop (SpaV4l2Source *this)
spa_v4l2_close (this);
return 0;
return SPA_RESULT_OK;
}