【原创】Linux v4l2框架分析

Read the fucking source code! --By 鲁迅

A picture is worth a thousand words. --By 高尔基

说明:

Kernel版本:4.14

ARM64处理器,Contex-A53,双核

使用工具:Source Insight 3.5, Visio

1. 概述

V4L2(Video for Linux 2):Linux内核中关于视频设备驱动的框架,对上向应用层提供统一的接口,对下支持各类复杂硬件的灵活扩展;

V4L2框架,主要包括v4l2-core、meida framework、videobuf2等模块,这也是本文将要展开的内容,仅提纲挈领;

开始吧。

2. v4l2-core 2.1 应用视角

先从应用的角度来看如何使用v4l2吧:

【原创】Linux v4l2框架分析

假如要进行视频数据采集,大体的步骤如上图左侧所示:

打开设备文件/dev/videoX;

根据打开的设备,查询设备能力集;

设置视频数据的格式、参数等;

分配buffer,这个buffer可以是用户态分配的,也可以是从内核中获取的;

开始视频流采集工作;

将buffer enqueue到v4l2框架,底层负责将视频数据填充后,应用层再将buffer dequeue以便获取数据,然后再将buffer enqueue,如此循环往复;

上图右侧是v4l2-core的大体框架,右侧是对硬件的抽象,要想理解好它,可以先看一下较常见的硬件拓扑结构:

【原创】Linux v4l2框架分析

通常一个camera的模组如图所示,通常包括Lens、Sensor、CSI接口等,其中CSI接口用于视频数据的传输;

SoC的Mipi接口对接Camera,并通过I2C/SPI控制camera模组;

Camera模组中也可以包含ISP模块,用于对图像进行处理,有的SoC中也集成了ISP的IP,接收camera的raw数据后,进行图像处理;

2.2 数据结构

如果以上图的硬件为例,对摄像头的硬件该怎么来抽象呢?没错,就是以v4l2_device和v4l2_subdev来进行抽象,以v4l2_device来代表整个输入设备,以v4l2_subdev来代表子模块,比如CSI、Sensor等;

【原创】Linux v4l2框架分析

v4l2_device:对视频设备的整体进行抽象,可以看成是一个纽带,将各个子设备联系在一起,通常它会嵌入在其他结构体中以提供v4l2框架的功能,比如strcut isp_device;

v4l2_subdev:对子设备进行抽象,该结构体中包含的struct v4l2_subdev_ops是一个完备的操作函数集,用于对接各种不同的子设备,比如video、audio、sensor等,同时还有一个核心的函数集struct v4l2_subdev_core_ops,提供更通用的功能。子设备驱动根据设备特点实现该函数集中的某些函数即可;

video_device:用于向系统注册字符设备节点,以便用户空间可以进行交互,包括各类设置以及数据buffer的获取等,在该结构体中也能看到struct v4l2_ioctl_ops和struct vb2_queue结构体字段,这些与上文中的应用层代码编写息息相关;

如果子设备不需要与应用层交互,struct v4l2_subdev中内嵌的video_device也可以不向系统注册字符设备;

video_device结构体,可以内嵌在其他结构体中,以便提供用户层交互的功能,比如struct isp_video;

针对图中回调函数集,v4l2-core提供了一些实现,所以driver在实现时,非特殊情况下可以不用重复造轮子;

2.3 流程分析

来进一步看一下内部的注册,及调用流程吧:

【原创】Linux v4l2框架分析

在驱动实现中,驱动结构体中内嵌struct video_device,同时实现struct v4l2_file_operations结构体中的函数,最终通过video_register_device向提供注册;

v4l2_register_device函数通过cdev_add向系统注册字符设备,并指定了file_operations,用户空间调用open/read/write/ioctl等接口,便可回调到驱动实现中;

v4l2_register_device函数中,通过device_register向系统注册设备,会在/sys文件系统下创建节点;

完成注册后,用户空间便可通过文件描述符来进行访问,从应用层看,大部分都是通过ioctl接口来完成,流程如下:

【原创】Linux v4l2框架分析

用户层的ioctl回调到__video_do_ioctl中,该函数会对系统提供的struct v4l2_ioctl_info v4l2_ioctls[]表进行查询,找到对应的项后进行调用;

驱动做的工作就是填空题,实现对应的回调,在合适的时候被调用;

下一个小节,让我们看看更复杂一点的情况。

3. media framework 3.1 问题引入

为了更好的描述,本节以omap3isp为例,先看一下它的硬件构成:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwxpdx.html