mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
v4l2: keep separate field for mapped fd
When mapping an input memfd, don't write the mapped pointer into the buffer but keep a separate field for it.
This commit is contained in:
parent
29dbffea52
commit
f37f8ce70d
2 changed files with 94 additions and 87 deletions
|
|
@ -65,6 +65,7 @@ struct buffer {
|
||||||
struct spa_meta_header *h;
|
struct spa_meta_header *h;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct v4l2_buffer v4l2_buffer;
|
struct v4l2_buffer v4l2_buffer;
|
||||||
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type {
|
struct type {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ static int spa_v4l2_open(struct impl *this)
|
||||||
|
|
||||||
if (xioctl(port->fd, VIDIOC_QUERYCAP, &port->cap) < 0) {
|
if (xioctl(port->fd, VIDIOC_QUERYCAP, &port->cap) < 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
perror("QUERYCAP");
|
spa_log_error(port->log, "QUERYCAP: %m");
|
||||||
return -err;
|
return -err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ static int spa_v4l2_buffer_recycle(struct impl *this, uint32_t buffer_id)
|
||||||
|
|
||||||
if (xioctl(port->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) {
|
if (xioctl(port->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) {
|
||||||
err = errno;
|
err = errno;
|
||||||
perror("VIDIOC_QBUF");
|
spa_log_error(port->log, "VIDIOC_QBUF: %m");
|
||||||
return -err;
|
return -err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -140,12 +140,10 @@ static int spa_v4l2_clear_buffers(struct impl *this)
|
||||||
spa_v4l2_buffer_recycle(this, i);
|
spa_v4l2_buffer_recycle(this, i);
|
||||||
}
|
}
|
||||||
if (SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_MAPPED)) {
|
if (SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_MAPPED)) {
|
||||||
if (d[0].data)
|
munmap(SPA_MEMBER(b->ptr, -d[0].mapoffset, void),
|
||||||
munmap(SPA_MEMBER(d[0].data, -d[0].mapoffset, void),
|
|
||||||
d[0].maxsize - d[0].mapoffset);
|
d[0].maxsize - d[0].mapoffset);
|
||||||
}
|
}
|
||||||
if (SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_ALLOCATED)) {
|
if (SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_ALLOCATED)) {
|
||||||
if (d[0].fd != -1)
|
|
||||||
close(d[0].fd);
|
close(d[0].fd);
|
||||||
}
|
}
|
||||||
d[0].type = SPA_ID_INVALID;
|
d[0].type = SPA_ID_INVALID;
|
||||||
|
|
@ -157,7 +155,7 @@ static int spa_v4l2_clear_buffers(struct impl *this)
|
||||||
reqbuf.count = 0;
|
reqbuf.count = 0;
|
||||||
|
|
||||||
if (xioctl(port->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
if (xioctl(port->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
||||||
perror("VIDIOC_REQBUFS");
|
spa_log_warn(port->log, "VIDIOC_REQBUFS: %m");
|
||||||
}
|
}
|
||||||
port->n_buffers = 0;
|
port->n_buffers = 0;
|
||||||
|
|
||||||
|
|
@ -177,7 +175,7 @@ static int spa_v4l2_close(struct impl *this)
|
||||||
spa_log_info(port->log, "v4l2: close");
|
spa_log_info(port->log, "v4l2: close");
|
||||||
|
|
||||||
if (close(port->fd))
|
if (close(port->fd))
|
||||||
perror("close");
|
spa_log_warn(port->log, "close: %m");
|
||||||
|
|
||||||
port->fd = -1;
|
port->fd = -1;
|
||||||
port->opened = false;
|
port->opened = false;
|
||||||
|
|
@ -581,7 +579,7 @@ spa_v4l2_enum_format(struct impl *this,
|
||||||
if ((res = xioctl(port->fd, VIDIOC_ENUM_FMT, &port->fmtdesc)) < 0) {
|
if ((res = xioctl(port->fd, VIDIOC_ENUM_FMT, &port->fmtdesc)) < 0) {
|
||||||
res = -errno;
|
res = -errno;
|
||||||
if (errno != EINVAL)
|
if (errno != EINVAL)
|
||||||
perror("VIDIOC_ENUM_FMT");
|
spa_log_error(port->log, "VIDIOC_ENUM_FMT: %m");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -625,7 +623,7 @@ spa_v4l2_enum_format(struct impl *this,
|
||||||
goto next_fmtdesc;
|
goto next_fmtdesc;
|
||||||
|
|
||||||
res = -errno;
|
res = -errno;
|
||||||
perror("VIDIOC_ENUM_FRAMESIZES");
|
spa_log_error(port->log, "VIDIOC_ENUM_FRAMESIZES: %m");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (filter) {
|
if (filter) {
|
||||||
|
|
@ -715,7 +713,7 @@ spa_v4l2_enum_format(struct impl *this,
|
||||||
goto next_frmsize;
|
goto next_frmsize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
perror("VIDIOC_ENUM_FRAMEINTERVALS");
|
spa_log_error(port->log, "VIDIOC_ENUM_FRAMEINTERVALS: %m");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (filter) {
|
if (filter) {
|
||||||
|
|
@ -872,13 +870,13 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
||||||
cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
|
cmd = try_only ? VIDIOC_TRY_FMT : VIDIOC_S_FMT;
|
||||||
if (xioctl(port->fd, cmd, &fmt) < 0) {
|
if (xioctl(port->fd, cmd, &fmt) < 0) {
|
||||||
res = -errno;
|
res = -errno;
|
||||||
perror("VIDIOC_S_FMT");
|
spa_log_error(port->log, "VIDIOC_S_FMT: %m");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some cheap USB cam's won't accept any change */
|
/* some cheap USB cam's won't accept any change */
|
||||||
if (xioctl(port->fd, VIDIOC_S_PARM, &streamparm) < 0)
|
if (xioctl(port->fd, VIDIOC_S_PARM, &streamparm) < 0)
|
||||||
perror("VIDIOC_S_PARM");
|
spa_log_warn(port->log, "VIDIOC_S_PARM: %m");
|
||||||
|
|
||||||
spa_log_info(port->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
|
spa_log_info(port->log, "v4l2: got %08x %dx%d %d/%d", fmt.fmt.pix.pixelformat,
|
||||||
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
fmt.fmt.pix.width, fmt.fmt.pix.height,
|
||||||
|
|
@ -1027,7 +1025,7 @@ spa_v4l2_enum_controls(struct impl *this,
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
res = -errno;
|
res = -errno;
|
||||||
perror("VIDIOC_QUERYCTRL");
|
spa_log_error(port->log, "VIDIOC_QUERYCTRL: %m");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (*index & next_fl)
|
if (*index & next_fl)
|
||||||
|
|
@ -1204,7 +1202,7 @@ static void v4l2_on_fd_events(struct spa_source *source)
|
||||||
|
|
||||||
static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers, uint32_t n_buffers)
|
static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers, uint32_t n_buffers)
|
||||||
{
|
{
|
||||||
struct port *state = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
struct v4l2_requestbuffers reqbuf;
|
struct v4l2_requestbuffers reqbuf;
|
||||||
int i;
|
int i;
|
||||||
struct spa_data *d;
|
struct spa_data *d;
|
||||||
|
|
@ -1214,11 +1212,11 @@ static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers,
|
||||||
|
|
||||||
if (d[0].type == this->type.data.MemFd ||
|
if (d[0].type == this->type.data.MemFd ||
|
||||||
(d[0].type == this->type.data.MemPtr && d[0].data != NULL)) {
|
(d[0].type == this->type.data.MemPtr && d[0].data != NULL)) {
|
||||||
state->memtype = V4L2_MEMORY_USERPTR;
|
port->memtype = V4L2_MEMORY_USERPTR;
|
||||||
} else if (d[0].type == this->type.data.DmaBuf) {
|
} else if (d[0].type == this->type.data.DmaBuf) {
|
||||||
state->memtype = V4L2_MEMORY_DMABUF;
|
port->memtype = V4L2_MEMORY_DMABUF;
|
||||||
} else {
|
} else {
|
||||||
spa_log_error(state->log, "v4l2: can't use buffers of type %s (%d)",
|
spa_log_error(port->log, "v4l2: can't use buffers of type %s (%d)",
|
||||||
spa_type_map_get_type (this->map, d[0].type), d[0].type);
|
spa_type_map_get_type (this->map, d[0].type), d[0].type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -1226,42 +1224,44 @@ static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers,
|
||||||
|
|
||||||
spa_zero(reqbuf);
|
spa_zero(reqbuf);
|
||||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
reqbuf.memory = state->memtype;
|
reqbuf.memory = port->memtype;
|
||||||
reqbuf.count = n_buffers;
|
reqbuf.count = n_buffers;
|
||||||
|
|
||||||
if (xioctl(state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
if (xioctl(port->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
||||||
spa_log_error(state->log, "v4l2: VIDIOC_REQBUFS %m");
|
spa_log_error(port->log, "v4l2: VIDIOC_REQBUFS %m");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
spa_log_info(state->log, "v4l2: got %d buffers", reqbuf.count);
|
spa_log_info(port->log, "v4l2: got %d buffers", reqbuf.count);
|
||||||
if (reqbuf.count < n_buffers) {
|
if (reqbuf.count < n_buffers) {
|
||||||
spa_log_error(state->log, "v4l2: can't allocate enough buffers");
|
spa_log_error(port->log, "v4l2: can't allocate enough buffers");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
|
|
||||||
b = &state->buffers[i];
|
b = &port->buffers[i];
|
||||||
b->outbuf = buffers[i];
|
b->outbuf = buffers[i];
|
||||||
b->flags = BUFFER_FLAG_OUTSTANDING;
|
b->flags = BUFFER_FLAG_OUTSTANDING;
|
||||||
b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header);
|
b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header);
|
||||||
|
|
||||||
spa_log_info(state->log, "v4l2: import buffer %p", buffers[i]);
|
spa_log_info(port->log, "v4l2: import buffer %p", buffers[i]);
|
||||||
|
|
||||||
if (buffers[i]->n_datas < 1) {
|
if (buffers[i]->n_datas < 1) {
|
||||||
spa_log_error(state->log, "v4l2: invalid memory on buffer %p", buffers[i]);
|
spa_log_error(port->log, "v4l2: invalid memory on buffer %p", buffers[i]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
d = buffers[i]->datas;
|
d = buffers[i]->datas;
|
||||||
|
|
||||||
spa_zero(b->v4l2_buffer);
|
spa_zero(b->v4l2_buffer);
|
||||||
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
b->v4l2_buffer.memory = state->memtype;
|
b->v4l2_buffer.memory = port->memtype;
|
||||||
b->v4l2_buffer.index = i;
|
b->v4l2_buffer.index = i;
|
||||||
|
|
||||||
if (d[0].type == this->type.data.MemFd && d[0].data == NULL) {
|
if (port->memtype == V4L2_MEMORY_USERPTR) {
|
||||||
|
if (d[0].data == NULL) {
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
data = mmap(NULL,
|
data = mmap(NULL,
|
||||||
d[0].maxsize + d[0].mapoffset,
|
d[0].maxsize + d[0].mapoffset,
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
|
@ -1270,20 +1270,24 @@ static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers,
|
||||||
if (data == MAP_FAILED)
|
if (data == MAP_FAILED)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
d[0].data = SPA_MEMBER(data, d[0].mapoffset, void);
|
b->ptr = SPA_MEMBER(data, d[0].mapoffset, void);
|
||||||
|
|
||||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
b->ptr = d[0].data;
|
||||||
|
|
||||||
if (d[0].type == this->type.data.MemPtr || d[0].type == this->type.data.MemFd) {
|
b->v4l2_buffer.m.userptr = (unsigned long) b->ptr;
|
||||||
b->v4l2_buffer.m.userptr = (unsigned long) d[0].data;
|
|
||||||
b->v4l2_buffer.length = d[0].maxsize;
|
b->v4l2_buffer.length = d[0].maxsize;
|
||||||
} else if (d[0].type == this->type.data.DmaBuf) {
|
}
|
||||||
|
else if (port->memtype == V4L2_MEMORY_DMABUF) {
|
||||||
b->v4l2_buffer.m.fd = d[0].fd;
|
b->v4l2_buffer.m.fd = d[0].fd;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
spa_v4l2_buffer_recycle(this, buffers[i]->id);
|
spa_v4l2_buffer_recycle(this, buffers[i]->id);
|
||||||
}
|
}
|
||||||
state->n_buffers = reqbuf.count;
|
port->n_buffers = reqbuf.count;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1295,53 +1299,53 @@ mmap_init(struct impl *this,
|
||||||
struct spa_buffer **buffers,
|
struct spa_buffer **buffers,
|
||||||
uint32_t *n_buffers)
|
uint32_t *n_buffers)
|
||||||
{
|
{
|
||||||
struct port *state = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
struct v4l2_requestbuffers reqbuf;
|
struct v4l2_requestbuffers reqbuf;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
state->memtype = V4L2_MEMORY_MMAP;
|
port->memtype = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
spa_zero(reqbuf);
|
spa_zero(reqbuf);
|
||||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
reqbuf.memory = state->memtype;
|
reqbuf.memory = port->memtype;
|
||||||
reqbuf.count = *n_buffers;
|
reqbuf.count = *n_buffers;
|
||||||
|
|
||||||
if (xioctl(state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
if (xioctl(port->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
||||||
spa_log_error(state->log, "VIDIOC_REQBUFS: %m");
|
spa_log_error(port->log, "VIDIOC_REQBUFS: %m");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_log_info(state->log, "v4l2: got %d buffers", reqbuf.count);
|
spa_log_info(port->log, "v4l2: got %d buffers", reqbuf.count);
|
||||||
*n_buffers = reqbuf.count;
|
*n_buffers = reqbuf.count;
|
||||||
|
|
||||||
if (reqbuf.count < 2) {
|
if (reqbuf.count < 2) {
|
||||||
spa_log_error(state->log, "v4l2: can't allocate enough buffers");
|
spa_log_error(port->log, "v4l2: can't allocate enough buffers");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
if (state->export_buf)
|
if (port->export_buf)
|
||||||
spa_log_info(state->log, "v4l2: using EXPBUF");
|
spa_log_info(port->log, "v4l2: using EXPBUF");
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
struct spa_data *d;
|
struct spa_data *d;
|
||||||
|
|
||||||
if (buffers[i]->n_datas < 1) {
|
if (buffers[i]->n_datas < 1) {
|
||||||
spa_log_error(state->log, "v4l2: invalid buffer data");
|
spa_log_error(port->log, "v4l2: invalid buffer data");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = &state->buffers[i];
|
b = &port->buffers[i];
|
||||||
b->outbuf = buffers[i];
|
b->outbuf = buffers[i];
|
||||||
b->flags = BUFFER_FLAG_OUTSTANDING | BUFFER_FLAG_ALLOCATED;
|
b->flags = BUFFER_FLAG_OUTSTANDING;
|
||||||
b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header);
|
b->h = spa_buffer_find_meta(b->outbuf, this->type.meta.Header);
|
||||||
|
|
||||||
spa_zero(b->v4l2_buffer);
|
spa_zero(b->v4l2_buffer);
|
||||||
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
b->v4l2_buffer.memory = state->memtype;
|
b->v4l2_buffer.memory = port->memtype;
|
||||||
b->v4l2_buffer.index = i;
|
b->v4l2_buffer.index = i;
|
||||||
|
|
||||||
if (xioctl(state->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) {
|
if (xioctl(port->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) {
|
||||||
perror("VIDIOC_QUERYBUF");
|
spa_log_error(port->log, "VIDIOC_QUERYBUF: %m");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1350,39 +1354,41 @@ mmap_init(struct impl *this,
|
||||||
d[0].maxsize = b->v4l2_buffer.length;
|
d[0].maxsize = b->v4l2_buffer.length;
|
||||||
d[0].chunk->offset = 0;
|
d[0].chunk->offset = 0;
|
||||||
d[0].chunk->size = 0;
|
d[0].chunk->size = 0;
|
||||||
d[0].chunk->stride = state->fmt.fmt.pix.bytesperline;
|
d[0].chunk->stride = port->fmt.fmt.pix.bytesperline;
|
||||||
|
|
||||||
if (state->export_buf) {
|
if (port->export_buf) {
|
||||||
struct v4l2_exportbuffer expbuf;
|
struct v4l2_exportbuffer expbuf;
|
||||||
|
|
||||||
spa_zero(expbuf);
|
spa_zero(expbuf);
|
||||||
expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
expbuf.index = i;
|
expbuf.index = i;
|
||||||
expbuf.flags = O_CLOEXEC | O_RDONLY;
|
expbuf.flags = O_CLOEXEC | O_RDONLY;
|
||||||
if (xioctl(state->fd, VIDIOC_EXPBUF, &expbuf) < 0) {
|
if (xioctl(port->fd, VIDIOC_EXPBUF, &expbuf) < 0) {
|
||||||
perror("VIDIOC_EXPBUF");
|
spa_log_error(port->log, "VIDIOC_EXPBUF: %m");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
d[0].type = this->type.data.DmaBuf;
|
d[0].type = this->type.data.DmaBuf;
|
||||||
d[0].fd = expbuf.fd;
|
d[0].fd = expbuf.fd;
|
||||||
d[0].data = NULL;
|
d[0].data = NULL;
|
||||||
|
SPA_FLAG_SET(b->flags, BUFFER_FLAG_ALLOCATED);
|
||||||
} else {
|
} else {
|
||||||
d[0].type = this->type.data.MemPtr;
|
d[0].type = this->type.data.MemPtr;
|
||||||
d[0].fd = -1;
|
d[0].fd = -1;
|
||||||
d[0].data = mmap(NULL,
|
d[0].data = mmap(NULL,
|
||||||
b->v4l2_buffer.length,
|
b->v4l2_buffer.length,
|
||||||
PROT_READ, MAP_SHARED,
|
PROT_READ, MAP_SHARED,
|
||||||
state->fd,
|
port->fd,
|
||||||
b->v4l2_buffer.m.offset);
|
b->v4l2_buffer.m.offset);
|
||||||
if (d[0].data == MAP_FAILED) {
|
if (d[0].data == MAP_FAILED) {
|
||||||
perror("mmap");
|
spa_log_error(port->log, "mmap: %m");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
b->ptr = d[0].data;
|
||||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
||||||
}
|
}
|
||||||
spa_v4l2_buffer_recycle(this, i);
|
spa_v4l2_buffer_recycle(this, i);
|
||||||
}
|
}
|
||||||
state->n_buffers = reqbuf.count;
|
port->n_buffers = reqbuf.count;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1405,16 +1411,16 @@ spa_v4l2_alloc_buffers(struct impl *this,
|
||||||
uint32_t *n_buffers)
|
uint32_t *n_buffers)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
struct port *state = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
|
|
||||||
if (state->n_buffers > 0)
|
if (port->n_buffers > 0)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (state->cap.capabilities & V4L2_CAP_STREAMING) {
|
if (port->cap.capabilities & V4L2_CAP_STREAMING) {
|
||||||
if ((res = mmap_init(this, params, n_params, buffers, n_buffers)) < 0)
|
if ((res = mmap_init(this, params, n_params, buffers, n_buffers)) < 0)
|
||||||
if ((res = userptr_init(this)) < 0)
|
if ((res = userptr_init(this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
} else if (state->cap.capabilities & V4L2_CAP_READWRITE) {
|
} else if (port->cap.capabilities & V4L2_CAP_READWRITE) {
|
||||||
if ((res = read_init(this)) < 0)
|
if ((res = read_init(this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
} else
|
} else
|
||||||
|
|
@ -1425,26 +1431,26 @@ spa_v4l2_alloc_buffers(struct impl *this,
|
||||||
|
|
||||||
static int spa_v4l2_stream_on(struct impl *this)
|
static int spa_v4l2_stream_on(struct impl *this)
|
||||||
{
|
{
|
||||||
struct port *state = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
|
|
||||||
if (!state->opened)
|
if (!port->opened)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (state->started)
|
if (port->started)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spa_log_debug(this->log, "starting");
|
spa_log_debug(this->log, "starting");
|
||||||
|
|
||||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
if (xioctl(state->fd, VIDIOC_STREAMON, &type) < 0) {
|
if (xioctl(port->fd, VIDIOC_STREAMON, &type) < 0) {
|
||||||
spa_log_error(this->log, "VIDIOC_STREAMON: %m");
|
spa_log_error(this->log, "VIDIOC_STREAMON: %m");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_loop_add_source(state->data_loop, &state->source);
|
spa_loop_add_source(port->data_loop, &port->source);
|
||||||
|
|
||||||
state->started = true;
|
port->started = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1456,41 +1462,41 @@ static int do_remove_source(struct spa_loop *loop,
|
||||||
size_t size,
|
size_t size,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct port *state = user_data;
|
struct port *port = user_data;
|
||||||
spa_loop_remove_source(state->data_loop, &state->source);
|
spa_loop_remove_source(port->data_loop, &port->source);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spa_v4l2_stream_off(struct impl *this)
|
static int spa_v4l2_stream_off(struct impl *this)
|
||||||
{
|
{
|
||||||
struct port *state = &this->out_ports[0];
|
struct port *port = &this->out_ports[0];
|
||||||
enum v4l2_buf_type type;
|
enum v4l2_buf_type type;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!state->opened)
|
if (!port->opened)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (!state->started)
|
if (!port->started)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spa_log_debug(this->log, "stopping");
|
spa_log_debug(this->log, "stopping");
|
||||||
|
|
||||||
spa_loop_invoke(state->data_loop, do_remove_source, 0, NULL, 0, true, state);
|
spa_loop_invoke(port->data_loop, do_remove_source, 0, NULL, 0, true, port);
|
||||||
|
|
||||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
if (xioctl(state->fd, VIDIOC_STREAMOFF, &type) < 0) {
|
if (xioctl(port->fd, VIDIOC_STREAMOFF, &type) < 0) {
|
||||||
spa_log_error(this->log, "VIDIOC_STREAMOFF: %m");
|
spa_log_error(this->log, "VIDIOC_STREAMOFF: %m");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
for (i = 0; i < state->n_buffers; i++) {
|
for (i = 0; i < port->n_buffers; i++) {
|
||||||
struct buffer *b;
|
struct buffer *b;
|
||||||
|
|
||||||
b = &state->buffers[i];
|
b = &port->buffers[i];
|
||||||
if (!SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_OUTSTANDING))
|
if (!SPA_FLAG_CHECK(b->flags, BUFFER_FLAG_OUTSTANDING))
|
||||||
if (xioctl(state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0)
|
if (xioctl(port->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0)
|
||||||
spa_log_warn(this->log, "VIDIOC_QBUF: %s", strerror(errno));
|
spa_log_warn(this->log, "VIDIOC_QBUF: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
state->started = false;
|
port->started = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue