關於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!!

 

沒那麼簡單...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章