1. 程式人生 > >從cimutils到核心-(2)VIDIOC_QUERYBUF(查詢buffer)

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