0%

Linux驱动之V4L2子系统

概述

V4L2 是专门为 linux 设备设计的一套视频框架,其主体框架在 linux 内核,可以理解为是整个 linux 系统上面的视频源捕获驱动框架。其广泛应用在嵌入式设备以及移动端、个人电脑设备上面,市面上的编码产品类如:SDV、手机、IPC、行车记录仪都会用到这个框架来进行视频采集。

框架

该图描述了v4l2驱动框架的整体结构,v4l2本质上也是一个字符设备驱动程序,图中芯片模块对应Soc的各个子模块,video_device结构体主要用来控制Soc的video模块,v4l2_device会包含多个v4l2_subdev ,每个v4l2_subdev 用来控制各自的子模块,某些驱动不需要v4l2_subdev ,依靠video模块就能实现功能。

  • video_device:一个字符设备,为用户空间提供设备节点(/dev/videoX),提供系统调用的相关操作,是采集设备的抽象接口
  • vb2_queue:与vb2_v4l2_buffer一起用于数据流的实际逻辑和DMA操作
  • v4l2_device:表示一个v4l2设备的实例
  • v4l2_subdev:属于v4l2设备的子设备,一个v4l2设备可以拥有多个子设备
  • videobuf:v4l2驱动的缓存管理

数据结构

整体数据结构如下:原图

  • v4l2_device
    这个是整个输入设备的总结构体,是所有子设备的根节点,负责管理所有子设备。由该结构体引申出来 v4l2_subdev。用于视频输入设备整体的管理,有多少输入设备就有多少个v4l2_device抽象(比如一个USB摄像头整体就可以看作是一个 V4L2 device)。再往下分是输入子设备,对应的是例如 ISP、CSI、MIPI 等设备,它们是从属于一个 V4L2 device 之下的

  • media_device
    用于运行时数据流的管理,嵌入在 V4L2 device 内部,运行时的意思就是:一个 V4L2 device 下属可能有非常多同类型的子设备(两个或者多个 sensor、ISP 等),那么在设备运行的时候我怎么知道我的数据流需要用到哪一个类型的哪一个子设备呢。这个时候就轮到 media_device 出手了,它为这一坨的子设备建立一条虚拟的连线,建立起来一个运行时的 pipeline(管道),并且可以在运行时动态改变、管理接入的设备

  • v4l2_ctrl_handler
    控制模块,提供子设备(主要是 video 和 ISP 设备)在用户空间的特效操作接口,比如你想改变下输出图像的亮度、对比度、饱和度等等,都可以通过这个来完成

  • v4l2_ctrl
    control 的结构体抽象,一个 control 就用一个实例化的 v4l2_ctrl 变量来表示

  • v4l2_ctrl_ref
    一个实例化的 v4l2_ctrl 的引用,可以看到该结构体里面包含了一个 struct v4l2_ctrl * 类型的指针变量成员,该指针成员指向的就是与之一一对应的 v4l2_ctrl 实例化对象

  • vb2_queue
    供内核与用户空间的 buffer 流转接口,输入设备产生了一坨图像数据,在内核里面应该放在哪里呢?能放几个呢?是整段连续的还是还是分段连续的又或者是物理不连续的?用户怎么去取用呢?都是它在管理

entity、link和pad该怎么理解呢,这里在网上找到一张图挺形象的,这里贴出来,如下:

待续...

参考文献

https://www.freesion.com/article/210999599/
https://yellowmax.blog.csdn.net/article/details/80718831
https://yellowmax.blog.csdn.net/article/details/83242446
https://blog.csdn.net/u013904227/article/details/80889947