V4L2音视频框架学习

一、什么是V4L2?

Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版。V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛的应用。

在Linux下,所有外设都被看成一种特殊的文件,成为“设备文件”,可以象访问普通文件一样对其进行读写。一般来说,采用V4L2驱动的摄像头设备文件是/dev/video0。V4L2支持两种方式来采集图像内存映射方式(mmap)和直接读取方式(read)。V4L2在include/linux/videodev2.h文件中定义了一些重要的数据结构,在采集图像的过程中,就是通过对这些数据的操作来获得最终的图像数据。Linux系统V4L2的能力可在Linux内核编译阶段配置,默认情况下都有此开发接口。

二、V4L2框架简介

几乎所有的设备都有多个 IC 模块,它们可能是实体的(例如 USB 摄像头里面包含 ISP、sensor 等)、也可能是抽象的(如 USB 设备里面的抽象拓扑结构),它们在 /dev 目录下面生成了多个设备节点,并且这些 IC 模块还创建了一些非 v4l2 设备:DVB、ALSA、FB、I2C 和输入设备。正是由于硬件的复杂性,v4l2 的驱动也变得非常复杂。

特别是 v4l2 驱动要支持 IC 模块来进行音/视频的混合/编解码操作,这就更加使得 v4l2 驱动变得异常复杂。通常情况下,有些IC模块通过一个或者多个 I2C 总线连接到主桥驱动上面,同时其它的总线仍然可用,这些 IC 就称为 ‘sub-devices’,比如摄像头设备里面的 sensor 传感器就是使用 I2C 来进行命令沟通,同时使用 MIPI 或者 LVDS 等接口进行图像数据传输。

在很长一段时间内,该框架(指老旧的 V4L2 框架)仅限于通过 video_device 结构体创建 v4l 设备节点和 video_buf 来处理视频数据。这意味着所有的驱动都必须对设备实例进行设置并将其映射到子设备上。有些时候这些操作步骤十分复杂,很难正确完成,并且有些驱动程序从来没有正确的按照这些操作步骤编写。由于缺少一个框架,有很多通用代码就没有办法被重构,从而导致这部分代码被重复编写,效率比较低下。

因此,本框架抽象构建了所有驱动都需要的代码并封装为一个个的模块,简化了设备驱动通用代码的重构。v4l2-pci-skeleton.c 是个非常好的参考例程,它是一个PCI采集卡的驱动框架。该例程演示了如何使用 v4l2 驱动框架,并且该例程可以作为一个 PCI 视频采集卡的驱动模板使用。在最开始的时候也可以参照这个代码编写方式进行联系,当然最适合的代码还是drivers/media/video/omap3isp 文件夹里面的代码,这个代码基本上可以作为一个完整的输入设备实例代码(因为它包含了 ISP、CSI、video 等设备,并且有着一个完整的数据流 pipeline,几乎用到了 V4L2 框架的方方面面,参考价值极大)来进行参考编写自己的设备驱动代码。

三、V4L2框架蓝图:

1、蓝图解构:

这是一张非常大的图,但是我只选取了其中的一个,这张图对 V4L2 里面的子模块进行简化(简化到只有子模块的名字,没有内部实现的介绍),大图如下:

图片
V4L2 设备拓扑

这张图怎么看呢?它有以下几个关键因素:

  • v4l2_device:这个是整个输入设备的总结构体,可以认为它是整个 V4L2 框架的入口,充当驱动的管理者以及入口监护人。由该结构体引申出来 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 设备)在用户空间的特效操作接口,比如你想改变下输出图像的亮度、对比度、饱和度等等,都可以通过这个来完成。
  • vb2_queue:提供内核与用户空间的 buffer 流转接口,输入设备产生了一坨图像数据,在内核里面应该放在哪里呢?能放几个呢?是整段连续的还是还是分段连续的又或者是物理不连续的?用户怎么去取用呢?都是它在管理。

2、层级解构:

  • 1、可以看到图中的入口 custom_v4l2_dev,它是由用户定义的一个结构体,重要的不是它怎么定义的,重要的是它里面有一个 v4l2_device 结构体,上文说到,这个结构体总览全局,运筹帷幄,相当于中央管理处的位置,那么中央决定了,它就是整个输入设备整体的抽象(比如整个 USB 摄像头输入设备,比如整个 IPC 摄像头输入设备)。它还有一个 media_device 结构体,上文也说道,,它是管数据流线路的,属于搞结构路线规划管理的。
  • 2、往后 v4l2_device 里面有一个链表,它维护了一个巨大的子设备链,所有的子设备都通过内核的双向循环链表结构以 v4l2_device 为中心紧紧团结在一起。另外 media_device 在往里面去就是一个个的 media_entity(现在不需要了解它的具体含义,只需要知道它就是类似电路板上面的元器件一样的抽象体),media_entity 之间建立了自己的小圈子,在它们这个小圈子里面数据流按照一定的顺序畅通无阻,恣意遨游。
  • 3、到结尾处,抽象出来了 /dev/videoX 设备节点,这个就是外交部的角色,它负责提供了一个内核与用户空间的交流枢纽。需要注意的是,该设备节点的本质还是一个字符设备,其内部的一套操作与字符设备是一样的,只不过是进行了一层封装而已。
  • 4、到此为止,一个 V4L2 大概的四层结构就抽象出来了,如下图所示:
图片

相关参考:

  • https://blog.csdn.net/weixin_43937576/article/details/109901691
  • https://yellowmax.blog.csdn.net/article/details/80718831

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论