关于vb2_buffer的操作描述

以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!!

 

没那么简单...

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值