v4l2: add support for DMABUF

Export dmafd on buffers and use those directly to send to the client.
Do some v4l2 cleanup.
This commit is contained in:
Wim Taymans 2016-07-13 19:56:39 +02:00
parent 17ef36c9c1
commit 16d2a3a69c
3 changed files with 61 additions and 18 deletions

View file

@ -199,11 +199,15 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
pinos_buffer_builder_init_into (&builder, buf, 1024, fdbuf, 8);
pinos_buffer_builder_add_header (&builder, &hdr);
fd = tmpfile_create (source, b->datas[0].data, b->size);
if (b->datas[0].type == SPA_DATA_TYPE_FD) {
fd = *((int *)b->datas[0].data);
} else {
fd = tmpfile_create (source, b->datas[0].data, b->size);
}
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
p.id = pinos_fd_manager_get_id (priv->fdmanager);
p.offset = 0;
p.size = b->size;
p.offset = b->datas[0].offset;
p.size = b->datas[0].size;
pinos_buffer_builder_add_fd_payload (&builder, &p);
pinos_buffer_builder_end (&builder, &pbuf);
@ -219,6 +223,7 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
g_clear_error (&error);
}
}
pinos_buffer_steal_fds (&pbuf, NULL);
pinos_buffer_unref (&pbuf);
spa_buffer_unref (b);

View file

@ -58,6 +58,7 @@ struct _V4l2Buffer {
bool outstanding;
struct v4l2_buffer v4l2_buffer;
V4l2Buffer *next;
int dmafd;
};
typedef struct {
@ -79,6 +80,7 @@ typedef struct {
SpaPortInfo info;
SpaAllocParam *params[1];
SpaAllocParamBuffers param_buffers;
bool export_buf;
SpaPortStatus status;
} SpaV4l2State;
@ -598,6 +600,8 @@ v4l2_source_init (const SpaHandleFactory *factory,
this->state[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
this->state[0].status.flags = SPA_PORT_STATUS_FLAG_NONE;
this->state[0].export_buf = true;
return SPA_RESULT_OK;
}

View file

@ -346,7 +346,6 @@ spa_v4l2_close (SpaV4l2Source *this)
state->fd = -1;
state->opened = false;
state->have_buffers = false;
return 0;
}
@ -530,22 +529,40 @@ mmap_init (SpaV4l2Source *this)
b->metas[0].data = &b->header;
b->metas[0].size = sizeof (b->header);
b->datas[0].type = SPA_DATA_TYPE_MEMPTR;
b->datas[0].data = mmap (NULL,
buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
state->fd,
buf.m.offset);
b->datas[0].offset = 0;
b->datas[0].size = buf.length;
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
b->outstanding = true;
if (state->export_buf) {
struct v4l2_exportbuffer expbuf;
if (b->datas[0].data == MAP_FAILED) {
perror ("mmap");
continue;
CLEAR (expbuf);
expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
expbuf.index = i;
if (xioctl (state->fd, VIDIOC_EXPBUF, &expbuf) < 0) {
perror("VIDIOC_EXPBUF");
continue;
}
b->dmafd = expbuf.fd;
b->datas[0].type = SPA_DATA_TYPE_FD;
b->datas[0].data = &b->dmafd;
b->datas[0].offset = 0;
b->datas[0].size = buf.length;
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
} else {
b->datas[0].type = SPA_DATA_TYPE_MEMPTR;
b->datas[0].data = mmap (NULL,
buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
state->fd,
buf.m.offset);
b->datas[0].offset = 0;
b->datas[0].size = buf.length;
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
if (b->datas[0].data == MAP_FAILED) {
perror ("mmap");
continue;
}
}
b->outstanding = true;
CLEAR (b->v4l2_buffer);
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@ -626,6 +643,7 @@ spa_v4l2_stop (SpaV4l2Source *this)
SpaV4l2State *state = &this->state[0];
enum v4l2_buf_type type;
SpaEvent event;
int i;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl (state->fd, VIDIOC_STREAMOFF, &type) < 0) {
@ -633,6 +651,22 @@ spa_v4l2_stop (SpaV4l2Source *this)
return -1;
}
for (i = 0; i < state->reqbuf.count; i++) {
V4l2Buffer *b;
b = &state->buffers[i];
if (b->outstanding) {
fprintf (stderr, "queueing outstanding buffer %p\n", b);
v4l2_buffer_free (b);
}
if (state->export_buf) {
close (b->dmafd);
} else {
munmap (b->datas[0].data, b->datas[0].size);
}
}
state->have_buffers = false;
event.refcount = 1;
event.notify = NULL;
event.type = SPA_EVENT_TYPE_REMOVE_POLL;