mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
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:
parent
17ef36c9c1
commit
16d2a3a69c
3 changed files with 61 additions and 18 deletions
|
|
@ -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_init_into (&builder, buf, 1024, fdbuf, 8);
|
||||||
pinos_buffer_builder_add_header (&builder, &hdr);
|
pinos_buffer_builder_add_header (&builder, &hdr);
|
||||||
|
|
||||||
|
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);
|
fd = tmpfile_create (source, b->datas[0].data, b->size);
|
||||||
|
}
|
||||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
|
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
|
||||||
p.id = pinos_fd_manager_get_id (priv->fdmanager);
|
p.id = pinos_fd_manager_get_id (priv->fdmanager);
|
||||||
p.offset = 0;
|
p.offset = b->datas[0].offset;
|
||||||
p.size = b->size;
|
p.size = b->datas[0].size;
|
||||||
pinos_buffer_builder_add_fd_payload (&builder, &p);
|
pinos_buffer_builder_add_fd_payload (&builder, &p);
|
||||||
pinos_buffer_builder_end (&builder, &pbuf);
|
pinos_buffer_builder_end (&builder, &pbuf);
|
||||||
|
|
||||||
|
|
@ -219,6 +223,7 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data)
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pinos_buffer_steal_fds (&pbuf, NULL);
|
||||||
pinos_buffer_unref (&pbuf);
|
pinos_buffer_unref (&pbuf);
|
||||||
|
|
||||||
spa_buffer_unref (b);
|
spa_buffer_unref (b);
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ struct _V4l2Buffer {
|
||||||
bool outstanding;
|
bool outstanding;
|
||||||
struct v4l2_buffer v4l2_buffer;
|
struct v4l2_buffer v4l2_buffer;
|
||||||
V4l2Buffer *next;
|
V4l2Buffer *next;
|
||||||
|
int dmafd;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -79,6 +80,7 @@ typedef struct {
|
||||||
SpaPortInfo info;
|
SpaPortInfo info;
|
||||||
SpaAllocParam *params[1];
|
SpaAllocParam *params[1];
|
||||||
SpaAllocParamBuffers param_buffers;
|
SpaAllocParamBuffers param_buffers;
|
||||||
|
bool export_buf;
|
||||||
SpaPortStatus status;
|
SpaPortStatus status;
|
||||||
} SpaV4l2State;
|
} SpaV4l2State;
|
||||||
|
|
||||||
|
|
@ -598,6 +600,8 @@ v4l2_source_init (const SpaHandleFactory *factory,
|
||||||
this->state[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
this->state[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||||
this->state[0].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
this->state[0].status.flags = SPA_PORT_STATUS_FLAG_NONE;
|
||||||
|
|
||||||
|
this->state[0].export_buf = true;
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,6 @@ spa_v4l2_close (SpaV4l2Source *this)
|
||||||
|
|
||||||
state->fd = -1;
|
state->fd = -1;
|
||||||
state->opened = false;
|
state->opened = false;
|
||||||
state->have_buffers = false;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -530,6 +529,24 @@ mmap_init (SpaV4l2Source *this)
|
||||||
b->metas[0].data = &b->header;
|
b->metas[0].data = &b->header;
|
||||||
b->metas[0].size = sizeof (b->header);
|
b->metas[0].size = sizeof (b->header);
|
||||||
|
|
||||||
|
if (state->export_buf) {
|
||||||
|
struct v4l2_exportbuffer expbuf;
|
||||||
|
|
||||||
|
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].type = SPA_DATA_TYPE_MEMPTR;
|
||||||
b->datas[0].data = mmap (NULL,
|
b->datas[0].data = mmap (NULL,
|
||||||
buf.length,
|
buf.length,
|
||||||
|
|
@ -540,12 +557,12 @@ mmap_init (SpaV4l2Source *this)
|
||||||
b->datas[0].offset = 0;
|
b->datas[0].offset = 0;
|
||||||
b->datas[0].size = buf.length;
|
b->datas[0].size = buf.length;
|
||||||
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
|
b->datas[0].stride = state->fmt.fmt.pix.bytesperline;
|
||||||
b->outstanding = true;
|
|
||||||
|
|
||||||
if (b->datas[0].data == MAP_FAILED) {
|
if (b->datas[0].data == MAP_FAILED) {
|
||||||
perror ("mmap");
|
perror ("mmap");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
b->outstanding = true;
|
||||||
|
|
||||||
CLEAR (b->v4l2_buffer);
|
CLEAR (b->v4l2_buffer);
|
||||||
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
|
@ -626,6 +643,7 @@ spa_v4l2_stop (SpaV4l2Source *this)
|
||||||
SpaV4l2State *state = &this->state[0];
|
SpaV4l2State *state = &this->state[0];
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
SpaEvent event;
|
SpaEvent event;
|
||||||
|
int i;
|
||||||
|
|
||||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
if (xioctl (state->fd, VIDIOC_STREAMOFF, &type) < 0) {
|
if (xioctl (state->fd, VIDIOC_STREAMOFF, &type) < 0) {
|
||||||
|
|
@ -633,6 +651,22 @@ spa_v4l2_stop (SpaV4l2Source *this)
|
||||||
return -1;
|
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.refcount = 1;
|
||||||
event.notify = NULL;
|
event.notify = NULL;
|
||||||
event.type = SPA_EVENT_TYPE_REMOVE_POLL;
|
event.type = SPA_EVENT_TYPE_REMOVE_POLL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue