從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對映記憶體。