videobuf是应用程序和v4l2驱动程序的一个中间层,用它来进行视频数据缓冲区的分配和管理。
它根据应用程序的需求(缓冲区的数量的大小),分配相应的视频缓冲区,这个缓冲区是在内核空间分配的,并通过mmap方法映射到用户空间,在内核空间形成一个缓冲区队列,在应用程序中有相应的缓冲区数组对应,它们指向的内存地址是一样的。在驱动程序中,根据配置的硬件参数(FIFO阈值),将vip硬件图像存储器中的数据放到缓冲区队列中的 每个缓冲区,然后等待应用程序来读取该缓冲区的数据。videobuf主要由一些特殊的数据结构和ioctl调用组成,下边对其做整体分析:
一、 初始化
初始化缓冲区队列:
1、驱动层的调用
在v4l2_vip.c文件中:
static int vip_open(struct file *file)
{
struct vip_dev *dev = video_drvdata(file);
struct vip_fh *fh = NULL;
int retval = 0;
、、、、、、、、、
/*allocate and initialize per filehandle data*/
fh = kzalloc(sizeof(*fh), GFP_KERNEL);//此时已经把vb_vidq成员的空间分配好
if(NULL == fh){
dev->users--;
retval = -ENOMEM;
}
、、、、、、、、、、
fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fh->fmt = &formats[0];
、、、、、、、、
/*初始化videobuf缓冲区队列 vip_video_qops 是驱动层的videobuf回掉函数*/
videobuf_queue_vmalloc_init(&fh->vb_vidq, &vip_video_qops, NULL,
&dev->slock, fh->type, V4L2_FIELD_INTERLACED,
sizeof(struct vip_buffer), fh);
return 0;
}
2、videobuf层的操作
在videobuf-vmalloc.c中:
videobuf_queue_vmalloc_init(struct videobuf_queue *q,
struct videobuf_queue_ops *ops,
struct device *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
unsigned int msize,
void *priv
)
{
videobuf_queue_core_init(q, ops, dev, irlock, type, field, msize, priv, &qops);
}
//上边函数多了一个qops参数,它是 videobuf层的数据操作函数集
void videobuf_queue_core_init(struct videobuf_queue *q,
struct videobuf_queue_ops *ops,
struct device *dev,
spinlock_t *irqlock,
enum v4l2_buf_type type,
enum v4l2_field field,
unsigned int msize,
void *priv,
struct videobuf_qtype_ops *int_ops)
{
BUG_ON(!q);
memset(q, 0, sizeof(*q));
//初始化队列的一些成员
q->irqlock = irqlock;
q->dev = dev;
q->type = type;
q->field = field;
q->msize = msize;
q->ops = ops;
q->priv_data = priv;
q->int_ops = int_ops;
//检测必要的成员数据是否不为空
/* All buffer operations are mandatory */
BUG_ON(!q->ops->buf_setup);
BUG_ON(!q->ops->buf_prepare);
BUG_ON(!q->ops->buf_queue);
BUG_ON(!q->ops->buf_release);
/* Lock is mandatory for queue_cancel to work */
BUG_ON(!irqlock);
/* Having implementations for abstract methods are mandatory */
BUG_ON(!q->int_ops);
mutex_init(&q->vb_lock);//初始化自旋锁
init_waitqueue_head(&q->wait);//初始化videobuf队列queue中的等待队列
INIT_LIST_HEAD(&q->stream);//初始化链表
}
二、 videobuf的相关ioctl()操作
这些操作有三部分组成,1是应用程序通过ioctl函数调用v4l2驱动中实现的接口函数,2这些接口函数在调用videobuf层的响应函数来做出处理,3如果有的处理参数需要v4l2层来决定的话,就调用v4l2层的videobuf设置函数。
1、ioctl接口函数列表
static const struct v4l2_ioctl_ops vip_capture_ioctl_fops = {
、、、、、、
.vidioc_reqbufs = vip_reqbufs,
.vidioc_querybuf = vip_querybuf,
.vidioc_qbuf = vip_qbuf,
.vidioc_dqbuf = vip_dqbuf,
.vidioc_streamon = vip_streamon,
.vidioc_streamoff = vip_streamoff,
、、、、、、
};
2、v4l2层设置回掉函数列表
Static struct videobuf_queue_ops vip_video_qops = {
.buf_setup = buffer_setbuf,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release &