深入学习Linux摄像头v4l2应用编程

  V4L2在设计时,是要支持很多广泛的设备的,它们之中只有一部分在本质上是真正的视频设备,能支持多种设备,它可以有以下几种接口

  video capture interface:视频采集接口,这种接口应用于摄像头,v4l2在最初设计的时候就是应用于这种功能

  video output interface:视频输出接口,将静止图像或图像序列编码为模拟视频信号,通过此接口,应用程序能控制编码过程并将图像从用户空间移动到驱动程序

  video overlay interface:视频直接传输接口,可以将采集到的视频数据直接传输到显示设备,不需要cpu参与,这种方式的显示图像的效率比其他方式高得多

  其中大多数操作都是通过应用层调用ioctl实现的,可以将这些ioctl分为下面几类

  由于V4L2涵盖了各种各样的设备,因此并非API的所有方面都适用于所有类型的设备,在使用v4l2设备时,必须调用此API,获得设备支持的功能(capture、output、overlay…)

  当多个应用程序共享设备时,在大多数情况下要为它们分配不同的优先级。视频录制应用程序能例如阻止其他应用程序改变视频控制或切换当前的电视频道。另一个目标是允许在后台工作的低优先级应用程序,这些应用程序能被用户控制的应用程序抢占,并在以后自动重新获得对设备的控制

  图像由多种格式YUV和RGB还有压缩格式等等,其中每种格式又分有多种格式,比如RGB:RGB565、RGB888…所以在使用设备时,需要对格式进行设置

  内核中使用缓存队列对图像数据来进行管理,用户空间获取图像数据有两种方式,一种是通过read、write方式读取内核空间的缓存,一种是将内核空间的缓存映射到用户空间。在操作v4l2设备时,通过VIDIOC_QUERYCAP获取设备支持哪种方式

  ioctl API就先介绍到这里,还有非常多的接口这里就不一一介绍了,具体能查看V4L2 Function Reference;下面来讲一讲怎么样去使用这些接口

  其中最重要的是capabilities字段,这个字段标记着v4l2设备的功能,capabilities有以下部分标记位:

  step 3:设置输入设备 一个设备可能有多个输入,比如:在芯片上,摄像头控制器和摄像头接口是分离的,要选择哪一个摄像头接口作为摄像头控制器的输入源

  当然,并不是所有的设备都需要设置输入,比如:uvc摄像头,一般只有一个输入,默认就会选择,不需要设置

  1.枚举输入设备 下面这段程序枚举了该设备所有的输入源,并打印输入源的名称:

  step 4:设置图像格式 有的摄像头支持多种像素格式,有的摄像头只支持一种像素格式,在设置格式之前,要先枚举出所有的格式,看一看是否支持要设置的格式,然后再进一步设置

  read方式很容易理解,是通过read函数读取,那么streaming是啥意思呢?

  streaming就是在内核空间中维护一个缓存队列,然后将内存映射到用户空间,应用读取图像数据就是一个不断地出队列和入队列的过程,如下图所示:

  因为若使用read方式读取的话,图像数据是从内核空间拷贝会应用空间,而一副图像的数据通常来说是比较大的,所以效率会比较低。而若使用映射的方式,讲内核空间的内存应用到用户空间,那么用户空间读取数据就想在操作内存一样,不需要经过内核空间到用户空间的拷贝,大幅度的提升效率

  映射缓存需要先查询缓存信息,然后再使用缓存信息进行映射,下面是一个例子:

  step 7:读取数据 获取图像数据其实就是一个不断地入队列和出队列地过程,在出队列前要调用poll等待数据准备完成

  出队列后得到了缓存的下标buffer.index,然后找到对饮的缓存,通过映射过后的地址进行数据的读取

  libv4l2 v4l2设备操作起来是比较繁琐的,为此我对其进行了封装,写了一套库,用起来更加方便,可以从这里libv4l2获取

  1.转换图像格式,将yuv格式转换成frame buff可以接收的rgb格式

  2.操作frame buff,通过映射frame buff的显存到用户空间,直接写显存就可以显示图像

  如何使用qt显示,道理跟在frame buff上显示是一样的,都是采集,转化格式,显示,只是在显示部分不同而已,这里给出一个例子。

其他人还喜欢