繼續v4l2分析

從很多資料上看到v4l2沒這麼簡單,摘自v4l2資料上的一段

Memory-Mapping Device Buffers - VIDIOC_REQBUFS, VIDIOC_QUERYBUF

These ioctls implement a general-purpose protocol for using mmap() to make driver buffers or device memory buffers accessible to the application for I/O.

To map buffers, the application first calls VIDIOC_REQBUFS with a struct v4l2_requestbuffers filled in with the number and type of the buffers that it wants. Upon return the driver will fill in how many buffers it will allow to be mapped, and possibly modify the type field as well. The application should make sure the granted count and type are ok. Note that it is possible that the driver may have a lower limit on the number of buffers required for streaming data. If the driver returns a count value greater than the requested number then that is a lower limit and the application needs to allocate at least that many buffers.

In general, drivers can support many sets of buffers. Each set of buffers is identified by a unique buffer type value. The sets are independent and each set can hold a different type of data.

To map the buffers call VIDIOC_QUERYBUF for each buffer to get the details about the buffer, and call mmap() to map it. VIDIOC_QUERYBUF takes a struct v4l2_buffer object with the index and type fields filled in to indicate which buffer is being queried. The type field must be filled in with the value from the struct v4l2_requestbuffers object. Valid index values range from 0 to count - 1, inclusive. Upon return, the offset and length fields will be filled in with the values that must be passed to mmap() to map the buffer. Only pass offset and length values received from the VIDIOC_QUERYBUF ioctl; the driver needs the exact values it indicated to correctly map the requested buffer. Use MAP_SHARED if the buffer will be used by a forked process. When the buffer is no longer needed the application must call munmap(). The application must munmap() before closing the driver.

VIDIOC_REQBUFS用於查詢緩衝數目,VIDIOC_QUERYBUF 用於申請緩衝,,接下來看

文件:/linux-2.6.19/drivers/media/video/mxc/output/Mx27_v4l2_output.c

mxc_v4l2out_ioctl-》video_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg))其中的func爲一個回調函數,(videodev.c)-> err = func(inode, file, cmd, parg);最後回調到Mx27_v4l2_output.c文件中來。
調用了mxc_v4l2out_do_ioctl 分析代碼:

case VIDIOC_REQBUFS:查詢緩衝

_vout_data-》dma_addr_t queue_buf_paddr[MAX_FRAME_NUM];就是一個地址數組30,存放從申請來的dma空間首地址。
mxc_allocate_buffers-》dma_alloc_coherent-- 獲取物理頁,並將該物理頁的總線地址保存於dma_handle,返回該物理頁的虛擬地址

void *
dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
void *ret;
if (!dev || *dev->dma_mask >= 0xffffffffUL)
gfp &= ~GFP_DMA;
ret = (void *)__get_free_pages(gfp, get_order(size)); //(1)
if (ret) {
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret); //(2)
}
return ret;
}

申請玩了緩衝,,就初始化相應個數的v4l2_buffer

case VIDIOC_QUERYBUF:

拷貝一個v4l2_buffer到出入的結構中去,每個緩衝的大小爲一幀的大小

問題又出現了,,這些驅動如何跟視頻驅動結合呢,如何送到輸出呢?

e:/vpu_test/test/mxc_vpu_test/Vpu_display.c文件下的v4l_put_data-》ioctrl(VIDIOC_QBUF)(調用驅動函數)

case VIDIOC_QBUF:

把index指出的buf,連接入一個隊列中去。queue_buf,而且還設了個定時器,timer

其處理函數爲mxc_v4l2out_timer_handler 分析函數:

主要就是/* Dequeue buffer and pass to PP */這樣顯示的任務就完成了




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