日期:2014-05-16  浏览次数:20785 次

深入理解linux内核v4l2框架之videobuf

Videobuf


下面来介绍以下videobuffer相关的一些东西。

V4L2核心api提供了一套标准的方法来处理视频缓冲,这些方法允许驱动实现read(),mmap(), overlay()等操作。同样也有方法支持DMAscatter/gather操作,并且支持vmallocbuffer(这个大多用在USB驱动上)

videobuf层功能是一种在v4l2驱动和用户空间当中的依附层,这话看起来有点绕,说白了就是提供一种功能框架,用来分配和管理视频缓冲区,它相对独立,却又被v4l2驱动使用。它有一组功能函数集用来实现许多标准的POSIX系统调用,包括read(),poll()mmap()等等,还有一组功能函数集用来实现流式(streaming)IOv4l2_ioctl调用,包括缓冲区的分配,入队和出队以及数据流控制等操作。使用videobuf需要驱动程序作者遵从一些强制的设计规则,但带来的好处是代码量的减少和v4l2框架API的一致。


缓冲类型

并不是所有的视频设备都使用相同的缓冲类型。实际上,有三种通用的类型:

被分散在物理和内核虚拟地址空间的缓冲,几乎所有的用户空间缓冲都是这种类型,


如果可能的话分配内核空间的缓冲也很有意义,但是不幸的是,这个通常需要那些支持离散聚合DMA操作的硬件设备。

物理上离散的但是虚拟地址是连续的,换句话说,就是用vmalloc分配的内核缓冲。这些缓冲很难用于DMA操作。

物理上连续的缓冲。

videobuf可以很好地处理这三种类型的缓冲,但是在此之前,驱动程序作者必须选择一种类型,并且以此类型为基础设计驱动。


数据结构,回调函数和初始化

根据选择的类型,包含不同的头文件,这些头文件在include/media/下面

<media/videobuf-dma-sg.h>

<media/videobuf-vmalloc.h>

<media/videobuf-dma-contig.h>

v4l2驱动需要包含一个videobuf_queue的实例用来管理缓冲队列,同时还要一个链表来维护这个队列,另外还要一个中断安全的spin_lock来保护队列的操作。

下一步就是要填充一个回调函数集来处理实际的缓冲区队列,这个函数集用videobuf_queue_ops来描述:

struct videobuf_queue_ops {

int *(buf_setup)(struct videobuf_queue*q, uint *count, uint *size);

int *(buf_prepare)(structvideobuf_queue *q, struct videobuf