博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于vb2_buffer的操作描述
阅读量:3557 次
发布时间:2019-05-20

本文共 31491 字,大约阅读时间需要 104 分钟。

以vivi驱动为例,

vb2_buffer为vivi设备内部使用的帧缓存描述, (用户态用v4l2_buffer来描述)

 

在vb2_queue队列中, 有两个队列, 分别为queued_list和done_list,

前者用于存放用户enqueue的buffer, 后者用于存放处理好等待dequeue的buffer。


Q: 贴段代码...

875 static void buffer_queue(struct vb2_buffer *vb)                                                                                                                                876 {                                                                                                                                                                              877 ›   struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);                                                                                                                    878 ›   struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);                                                                                                        879 ›   struct vivi_dmaqueue *vidq = &dev->vidq;                                                                                                                                   880 ›   unsigned long flags = 0;                                                                                                                                                   881                                                                                                                                                                                882 ›   dprintk(dev, 1, "%s\n", __func__);                                                                                                                                         883                                                                                                                                                                                884 ›   spin_lock_irqsave(&dev->slock, flags);                                                                                                                                     885 ›   list_add_tail(&buf->list, &vidq->active);                                                                                                                                  886 ›   spin_unlock_irqrestore(&dev->slock, flags);                                                                                                                                887 }

list_add_tail的是&buf->list指针, 它是谁? 

185 /* buffer for one video frame */                                                                                                                                               186 struct vivi_buffer {                                                                                                                                                           187 ›   /* common v4l buffer stuff -- must be first */                                                                                                                             188 ›   struct vb2_buffer›  vb;                                                                                                                                                    189 ›   struct list_head›   list;                                                                                                                                                  190 };

它是vivi_buffer的list_head变量。 有一行注释, /* common v4l buffer stuff -- must be first */

这里很奇怪, 搜索vivi_buffer没有找到直接分配的地方....

为什么这里能用struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); 获取到vivi_buffer结构体变量的开头指针??

vb2_buffer不是在reqbufs过程中分配的吗?  为什么能用核心层分配的变量取到vivi驱动中的vivi_buffer结构体指针。。。

A:  没错, vb2_buffer就是reqbufs分配的, 进去看看就明白了....


Q: vb2_buffer什么时候被分配?

A: 在reqbufs时分配, 即用户调用VIDIOC_REQBUFS时,  驱动根据用户需求, 分配对应buffer数。

调用序列: VIDIOC_REQBUFS->vb2_ioctl_reqbufs->__reqbufs->__vb2_queue_alloc

贴下__reqbufs函数注释, 干的活挺多的...

843 /**                                                                                                                                                                                                      844  * __reqbufs() - Initiate streaming                                                                                                                                                                      845  * @q:› ›   videobuf2 queue                                                                                                                                                                              846  * @req:›   struct passed from userspace to vidioc_reqbufs handler in driver                                                                                                                             847  *                                                                                                                                                                                                       848  * Should be called from vidioc_reqbufs ioctl handler of a driver.                                                                                                                                       849  * This function:                                                                                                                                                                                        850  * 1) verifies streaming parameters passed from the userspace,                                                                                                                                           851  * 2) sets up the queue,                                                                                                                                                                                 852  * 3) negotiates number of buffers and planes per buffer with the driver                                                                                                                                 853  *    to be used during streaming,                                                                                                                                                                       854  * 4) allocates internal buffer structures (struct vb2_buffer), according to                                                                                                                             855  *    the agreed parameters,                                                                                                                                                                             856  * 5) for MMAP memory type, allocates actual video memory, using the                                                                                                                                     857  *    memory handling/allocation routines provided during queue initialization                                                                                                                           858  *                                                                                                                                                                                                       859  * If req->count is 0, all the memory will be freed instead.                                                                                                                                             860  * If the queue has been allocated previously (by a previous vb2_reqbufs) call                                                                                                                           861  * and the queue is not busy, memory will be reallocated.                                                                                                                                                862  *                                                                                                                                                                                                       863  * The return values from this function are intended to be directly returned                                                                                                                             864  * from vidioc_reqbufs handler in driver.                                                                                                                                                                865  */                                                                                                                                                                                                      866 static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)

其中有两步,  sets up the queue 和 allocates internal buffer structures。

913 ›   /*                                                                                                                                                                                                   914 ›    * Ask the driver how many buffers and planes per buffer it requires.                                                                                                                                915 ›    * Driver also sets the size and allocator context for each plane.                                                                                                                                   916 ›    */                                                                                                                                                                                                  917 ›   ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,                                                                                                                                   918 ›   ›          q->plane_sizes, q->alloc_ctx);                                                                                                                                                            919 ›   if (ret)                                                                                                                                                                                             920 ›   ›   return ret;                                                                                                                                                                                      921                                                                                                                                                                                                          922 ›   /* Finally, allocate buffers and video memory */                                                                                                                                                     923 ›   allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);                                                                                                                      924 ›   if (allocated_buffers == 0) {                                                                                                                                                                        925 ›   ›   dprintk(1, "memory allocation failed\n");                                                                                                                                                        926 ›   ›   return -ENOMEM;                                                                                                                                                                                  927 ›   }

即会调用驱动queue_setup函数进行buffer设置, 如该驱动提供的buffer数量, plane层数, 以及buffer大小等。

之后调用__vb2_queue_alloc进行真实的buffer分配。

函数不算长, 直接全贴下。

337 /**                                                                                                                                                                                                                                                             338  * __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP type)                                                                                                                                                                                339  * video buffer memory for all buffers/planes on the queue and initializes the                                                                                                                                                                                  340  * queue                                                                                                                                                                                                                                                        341  *                                                                                                                                                                                                                                                              342  * Returns the number of buffers successfully allocated.                                                                                                                                                                                                        343  */                                                                                                                                                                                                                                                             344 static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,                                                                                                                                                                                      345 ›   ›   ›        unsigned int num_buffers, unsigned int num_planes)                                                                                                                                                                                             346 {                                                                                                                                                                                                                                                               347 ›   unsigned int buffer;                                                                                                                                                                                                                                        348 ›   struct vb2_buffer *vb;                                                                                                                                                                                                                                      349 ›   int ret;                                                                                                                                                                                                                                                    350                                                                                                                                                                                                                                                                 351 ›   for (buffer = 0; buffer < num_buffers; ++buffer) {                                                                                                                                                                                                          352 ›   ›   /* Allocate videobuf buffer structures */                                                                                                                                                                                                               353 ›   ›   vb = kzalloc(q->buf_struct_size, GFP_KERNEL);                                                                                                                                                                                                           354 ›   ›   if (!vb) {                                                                                                                                                                                                                                              355 ›   ›   ›   dprintk(1, "memory alloc for buffer struct failed\n");                                                                                                                                                                                              356 ›   ›   ›   break;                                                                                                                                                                                                                                              357 ›   ›   }                                                                                                                                                                                                                                                       358                                                                                                                                                                                                                                                                 359 ›   ›   /* Length stores number of planes for multiplanar buffers */                                                                                                                                                                                            360 ›   ›   if (V4L2_TYPE_IS_MULTIPLANAR(q->type))                                                                                                                                                                                                                  361 ›   ›   ›   vb->v4l2_buf.length = num_planes;                                                                                                                                                                                                                   362                                                                                                                                                                                                                                                                 363 ›   ›   vb->state = VB2_BUF_STATE_DEQUEUED;                                                                                                                                                                                                                     364 ›   ›   vb->vb2_queue = q;                                                                                                                                                                                                                                      365 ›   ›   vb->num_planes = num_planes;                                                                                                                                                                                                                            366 ›   ›   vb->v4l2_buf.index = q->num_buffers + buffer;                                                                                                                                                                                                           367 ›   ›   vb->v4l2_buf.type = q->type;                                                                                                                                                                                                                            368 ›   ›   vb->v4l2_buf.memory = memory;                                                                                                                                                                                                                           369                                                                                                                                                                                                                                                                 370 ›   ›   /* Allocate video buffer memory for the MMAP type */                                                                                                                                                                                                    371 ›   ›   if (memory == V4L2_MEMORY_MMAP) {                                                                                                                                                                                                                       372 ›   ›   ›   ret = __vb2_buf_mem_alloc(vb);                                                                                                                                                                                                                      373 ›   ›   ›   if (ret) {                                                                                                                                                                                                                                          374 ›   ›   ›   ›   dprintk(1, "failed allocating memory for "                                                                                                                                                                                                      375 ›   ›   ›   ›   ›   ›   "buffer %d\n", buffer);                                                                                                                                                                                                                 376 ›   ›   ›   ›   kfree(vb);                                                                                                                                                                                                                                      377 ›   ›   ›   ›   break;                                                                                                                                                                                                                                          378 ›   ›   ›   }                                                                                                                                                                                                                                                   379 ›   ›   ›   /*                                                                                                                                                                                                                                                  380 ›   ›   ›    * Call the driver-provided buffer initialization                                                                                                                                                                                                   381 ›   ›   ›    * callback, if given. An error in initialization                                                                                                                                                                                                   382 ›   ›   ›    * results in queue setup failure.                                                                                                                                                                                                                  383 ›   ›   ›    */                                                                                                                                                                                                                                                 384 ›   ›   ›   ret = call_vb_qop(vb, buf_init, vb);                                                                                                                                                                                                                385 ›   ›   ›   if (ret) {                                                                                                                                                                                                                                          386 ›   ›   ›   ›   dprintk(1, "buffer %d %p initialization"                                                                                                                                                                                                        387 ›   ›   ›   ›   ›   " failed\n", buffer, vb);                                                                                                                                                                                                                   388 ›   ›   ›   ›   __vb2_buf_mem_free(vb);                                                                                                                                                                                                                         389 ›   ›   ›   ›   kfree(vb);                                                                                                                                                                                                                                      390 ›   ›   ›   ›   break;                                                                                                                                                                                                                                          391 ›   ›   ›   }                                                                                                                                                                                                                                                   392 ›   ›   }                                                                                                                                                                                                                                                       393                                                                                                                                                                                                                                                                 394 ›   ›   q->bufs[q->num_buffers + buffer] = vb;                                                                                                                                                                                                                  395 ›   }                                                                                                                                                                                                                                                           396                                                                                                                                                                                                                                                                 397 ›   __setup_lengths(q, buffer);                                                                                                                                                                                                                                 398 ›   if (memory == V4L2_MEMORY_MMAP)                                                                                                                                                                                                                             399 ›   ›   __setup_offsets(q, buffer);                                                                                                                                                                                                                             400                                                                                                                                                                                                                                                                 401 ›   dprintk(1, "allocated %d buffers, %d plane(s) each\n",                                                                                                                                                                                                      402 ›   ›   ›   buffer, num_planes);                                                                                                                                                                                                                                403                                                                                                                                                                                                                                                                 404 ›   return buffer;                                                                                                                                                                                                                                              405 }

这里有个关键点,

struct vb2_buffer *vb;

vb = kzalloc(p->buf_struct_size, GFP_KERNEL);

为什么分配的内存大小是buf_struct_size而不是sizeof(vb2_buffer)??

是的, 这就是问题1的答案, 这里预先分配的其实就是vivi_buffer的内存。

而不是vb2_buffer的内存。

vivi.c里找找, 很容易就找到buf_struct_size了...

1437 ›   /* initialize queue */                                                                                                                                                    1438 ›   q = &dev->vb_vidq;                                                                                                                                                        1439 ›   q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;                                                                                                                                    1440 ›   q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;                                                                                                             1441 ›   q->drv_priv = dev;                                                                                                                                                        1442 ›   q->buf_struct_size = sizeof(struct vivi_buffer);                                                                                                                          1443 ›   q->ops = &vivi_video_qops;                                                                                                                                                1444 ›   q->mem_ops = &vb2_vmalloc_memops;                                                                                                                                         1445 ›   q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;                                                                                                                   1446                                                                                                                                                                               1447 ›   ret = vb2_queue_init(q);

q->buf_struct_size = sizeof(struct vivi_buffer);

初始化queue的时候就跟vivi 核心层说了,  我要的buffer不是vb2_buffer, 而是vivi_buffer!!

 

没那么简单...

转载地址:http://npcrj.baihongyu.com/

你可能感兴趣的文章
安装rabbitmq时踩的坑
查看>>
2021-06-09数据库添加多条数据
查看>>
简单的JAVA小作品
查看>>
CMake下载
查看>>
未调用fflush产生的图片文件无法打开问题
查看>>
SQL 约束(二)
查看>>
SQL ALTER用法(三)
查看>>
SQL where子句及查询条件语句(六)
查看>>
SQL 连接JOIN(九)
查看>>
linux VM虚拟机可以ping通主机,但主机无法ping通虚拟机
查看>>
linux 错误码
查看>>
C++ 中Struct与typedef struct总结
查看>>
WNetAddConnection2调用失败,错误码1200/1312
查看>>
POI读写Excel的基本使用
查看>>
淘宝网站的架构演进
查看>>
设置zookeeper开机自启动流程
查看>>
CentOS安装mysql5.7的教详细流程
查看>>
项目整合微信扫码登录功能
查看>>
分布式文件系统FastDfs的搭建
查看>>
Springboot项目利用Java客户端调用FastDFS
查看>>