从cimutils到内核-(2)VIDIOC_QUERYBUF(查询buffer)

应用层:

循环两次去获取内核申请的两个buffer的起始地址,通过这两个地址用mmap映射,这样用户层可以通过操作这两个地址,访问内存空间的buffer

for (n_buffers=0; n_buffers<req.count; ++n_buffers) { //循环两次,询问两次buffer

struct v4l2_buffer buf;

CLEAR(buf);

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory = V4L2_MEMORY_MMAP;

buf.index = n_buffers; //把结构体 struct v4l2_buffer的内容从用户层传递到内核 分别是buffers[0] buffers[1]往内核里传递

if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))

errno_exit("VIDIOC_QUERYBUF");

buffers[n_buffers].length = buf.length;

buffers[n_buffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); //映射内存 buffers[0] buffers[1]

if (MAP_FAILED == buffers[n_buffers].start)

errno_exit("mmap");

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

内核:

(1)

drivers/media/v4l2-core/v4l2-ioctl.c

IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length))

static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,

struct file *file, void *fh, void *arg)

{

struct v4l2_buffer *p = arg;

int ret = check_fmt(file, p->type);

return ret ? ret : ops->vidioc_querybuf(file, fh, p);

}

(2)

drivers/media/platform/soc_camera/soc_camera.c

static int soc_camera_querybuf(struct file *file, void *priv,

struct v4l2_buffer *p)

{

struct soc_camera_device *icd = file->private_data;

struct soc_camera_host *ici = to_soc_camera_host(icd->parent);

WARN_ON(priv != file->private_data);

if (ici->ops->init_videobuf)

return videobuf_querybuf(&icd->vb_vidq, p);

else

return vb2_querybuf(&icd->vb2_vidq, p);

}

(3)

drivers/media/v4l2-core/videobuf2-core.c

int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)

{

struct vb2_buffer *vb;

int ret;

if (b->type != q->type) {

dprintk(1, "querybuf: wrong buffer type\n");

return -EINVAL;

}

if (b->index >= q->num_buffers) {

dprintk(1, "querybuf: buffer index out of range\n");

return -EINVAL;

}

vb = q->bufs[b->index];

ret = __verify_planes_array(vb, b);

if (!ret)

__fill_v4l2_buffer(vb, b);

//(根据申请的结构体struct vb2_buffer *vb内容去填充结构体struct v4l2_buffer *b返回给用户空间)fill in a struct v4l2_buffer with information to be returned to userspace

return ret;

}

EXPORT_SYMBOL(vb2_querybuf);

总结:

主要给用户空间返回buffer的大小和每个buffer开始的偏移地址,方便应用层mmap映射内存。

猜你喜欢

转载自blog.csdn.net/sinat_37817094/article/details/83815606
今日推荐