V4L2 input/output方式

V4L2 API 定义了几种数据传输方式从video设备读写数据,驱动要和应用进行数据交换就必须支持其中的一种

经典的I/O方法是打开V4L2 设备后就可以使用的read()和write()方法。驱动可以不支持read/write方式,此时read/write操作会返回错误。

其他的I/O方法必须通过协商的方式执行;streaming I/O模式:应用在调用VIDIOC_REQBUFS时确定是memory mapped还是user buffers;以及V4L2 API还未实现的asynchronous I/O

Video overlay可以被认为是另外一种形式的的I/O模式,尽管应用无法从V4L2设备接收image数据


Read/Write

如果输入和输出设备支持read/write操作,那么VIDIOC_QUERYCAP ioctl返回的v4l2_capability结构的capabilities成员要包含V4L2_CAP_READWRITE标志。

和stream I/O模式相比,read/write需要CPU拷贝数据,(当然stream I/O的user pointers也需要数据拷贝,如果user pointers不是连续的物理页面,而驱动的DMA又需要大块连续物理页面)。此外和stream-io模式相比,read/write无法获取meta-information而被看作是较低级的I/O操作,比如帧计数和时间戳等,这些meta-information是识别掉帧以及和其他数据流同步的必要数据。当然Read/Write是最简单的I/O方式,所以编码更简单。


Streaming I/O (Memory Mapping)

如果输入和输出设备支持Stream I/O操作,那么VIDIOC_QUERYCAP ioctl返回的v4l2_capability结构的capabilities成员要包含V4L2_CAP_STREAMING标志。

Streaming I/O方式仅仅buffers的指针在application和driver间交换,数据本身不会做copy。memory mapping主要是把设备中的物理内存映射为应用的地址空间。设备的物理内存可以是图形卡的video内存,也可以是主存中的DMA内存。

一个驱动可以支持多组buffers。每一组被唯一的buffer 类型值标识。每一组buffers是独立的保存着不同类型的数据。同时访问不同类型的数据需要使用不同的file描述符。

应用调用VIDIOC_REQBUFS ioctl分配设备buffers,参数标识需要的数目和类型。这个ioctl也可以用来改变buffers的数据以及释放分配的内存。

在应用能够访问这些buffers之前,必须调用mmap函数把这些物理地址映射为用户空间地址,这些buffers在设备空间的物理位置是通过VIDIOC_QUERYBUF获得的的,VIDIOC_QUERYBUF会设置v4l2_buffer结构,在single-planar模式下buf.m.offset和buf.length返回buffer物理地址以及buffer的长度。当用做multi-planar API时,每一层的buffer都需要单独map,也就是说调用mmap的次数是每一个buffer所包含的planar的数目

记住,buffers是分配的物理内存,应用在使用完这些buffers后,要通过munmap()函数释放虚拟内存地址空间,而物理内存的释放是通过VIDIOC_REQBUFS来实现的(设置参数buf count为(0)


概念上说streaming驱动维护着两个buffer队列,输入队列和输出队列。由于同步capture或output操作是实时操作的,引入这两个队列可以避免由于磁盘,网络延迟以及被其他应用进程取代造成的数据丢失。队列是按照FIFOs组织的,buffers输出顺序按照输入队列的入队顺序,capture则是按照输出队列的出队顺序


Streaming I/O (User Pointers)

这种I/O结合了read/write和memory mapping的优点,application分配Buffers(包括planes),buffers是虚拟内存或者共享内存。驱动和应用间通过数据指针交换数据,

这些指针和meta-information通过结构v4l2_buffer传递。


application在应用空间为每一个buffers分配了空间,由于这个空间是虚拟的地址空间,所以这就意味着v4l2设备驱动必须进行数据的copy,从驱动的DMA内存复制到用户地址空间

你可能感兴趣的:(Stream,user,application,buffer,asynchronous,Pointers)