继续v4l2分析

来源:互联网 发布:java accept函数 编辑:程序博客网 时间:2024/05/17 18:49

从很多资料上看到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 */这样显示的任务就完成了