0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核中视频设备驱动框架V4L2X详解

xCb1_yikoulinux 来源:LoyenWang 作者:LoyenWang 2022-05-30 16:18 次阅读

背景

  • Read the ***ing source code! --By 鲁迅
  • A picture is worth a thousand words. --By 高尔基

说明:

  1. Kernel版本:4.14
  2. ARM64处理器,Contex-A53,双核
  3. 使用工具:Source Insight 3.5, Visio

1. 概述

  • V4L2(Video for Linux 2):Linux内核中关于视频设备驱动的框架,对上向应用层提供统一的接口,对下支持各类复杂硬件的灵活扩展;
  • V4L2框架,主要包括v4l2-coremeida frameworkvideobuf2等模块,这也是本文将要展开的内容,仅提纲挈领;

开始吧。

2. v4l2-core

2.1 应用视角

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

dbc33532-df35-11ec-ba43-dac502259ad0.png

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

  1. 打开设备文件/dev/videoX
  2. 根据打开的设备,查询设备能力集;
  3. 设置视频数据的格式、参数等;
  4. 分配buffer,这个buffer可以是用户态分配的,也可以是从内核中获取的;
  5. 开始视频流采集工作;
  6. 将buffer enqueue到v4l2框架,底层负责将视频数据填充后,应用层再将buffer dequeue以便获取数据,然后再将buffer enqueue,如此循环往复;

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

dc159cbe-df35-11ec-ba43-dac502259ad0.png

  • 通常一个camera的模组如图所示,通常包括Lens、Sensor、CSI接口等,其中CSI接口用于视频数据的传输;
  • SoC的Mipi接口对接Camera,并通过I2C/SPI控制camera模组;
  • Camera模组中也可以包含ISP模块,用于对图像进行处理,有的SoC中也集成了ISP的IP,接收camera的raw数据后,进行图像处理;

2.2 数据结构

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

dc2d850e-df35-11ec-ba43-dac502259ad0.png

  • 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_opsstruct vb2_queue结构体字段,这些与上文中的应用层代码编写息息相关;
  • 如果子设备不需要与应用层交互,struct v4l2_subdev中内嵌的video_device也可以不向系统注册字符设备;
  • video_device结构体,可以内嵌在其他结构体中,以便提供用户层交互的功能,比如struct isp_video
  • 针对图中回调函数集,v4l2-core提供了一些实现,所以driver在实现时,非特殊情况下可以不用重复造轮子;

2.3 流程分析

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

dc878770-df35-11ec-ba43-dac502259ad0.png

  • 在驱动实现中,驱动结构体中内嵌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接口来完成,流程如下:

dcc441ec-df35-11ec-ba43-dac502259ad0.png

  • 用户层的ioctl回调到__video_do_ioctl中,该函数会对系统提供的struct v4l2_ioctl_info v4l2_ioctls[]表进行查询,找到对应的项后进行调用;
  • 驱动做的工作就是填空题,实现对应的回调,在合适的时候被调用;

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

3. media framework

3.1 问题引入

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

dd1d4896-df35-11ec-ba43-dac502259ad0.png

  • CSI:camera接口,接收图像数据,RGB/YUV/JPEG等;
  • CCDC:视频处理前端,CCDC为图像传感器和数字视频源提供接口,并处理图像数据;
  • Preview/Resizer:视频处理后端,Preview提供预览功能,可针对不同类型的传感器进行定制,Resizer提供将输入图像数据按所需的显示或视频编码分辨率调整大小的方法;
  • H3A/HIST:静态统计模块,H3A支持AF、AWB、AE的回路控制,HIST根据输入数据,提供各种3A算法所需的统计数据;

上述硬件模块,可以对应到驱动结构体struct isp_device中的各个字段。

omap3isp的硬件模块,支持多种数据流通路,它并不是唯一的,以RGB为例,如下图:

dd6410be-df35-11ec-ba43-dac502259ad0.png

  • Raw RGB数据进入ISP模块后,可以在运行过程中,根据实际的需求进行通路设置;
  • 所以,重点是:它需要动态设置路径!

那么,软件该如何满足这种需求呢?

3.2 框架

没错,pipeline框架的引入可以解决这个问题。说来很巧,我曾经也实现过一个类似的框架,在阅读media framework时有一种似曾相识的感觉,核心的思想大体一致。

ddb4e35e-df35-11ec-ba43-dac502259ad0.png

  • 模块之间相互独立,通过struct media_entity来进行抽象,通常会将struct media_entity嵌入到其他结构中,以支持media framework功能;
  • entity模块包含struct media_pad,pad可以认为是端口,与其他模块进行联系的媒介,针对特定模块来说它是确定的;
  • pad通过struct media_link来建立连接,指定source和sink,即可将通路建立起来;
  • 各个模块之间最终建立一条数据流,便是一条pipeline了,同一条pipeline中的模块,可以根据前一个模块查找到下一个模块,因此也可以很方便进行遍历,并做进一步的设置操作;

因此,只需要将struct media_entity嵌入到特定子模块中,最终便可以将子模块串联起来,构成数据流。所以,omap3isp的驱动中,数据流就如下图所示:

dddd3ffc-df35-11ec-ba43-dac502259ad0.png

  • video devnode代表video device,也就是前文中提到的导出到用户空间的节点,用于与用户进行控制及数据交互;
  • 每个模块分别有source pad和sink pad,从连接图就可以看出,数据通路灵活多变;
  • 至于数据通路选择问题,可以在驱动初始化的时候进行链接创建,比如isp_create_links

还是看一下数据结构吧:

de02293e-df35-11ec-ba43-dac502259ad0.png

  • media_device:与v4l2_device类似,也是负责将各个子模块集中进行管理,同时在注册的时候,会向系统注册设备节点,方便用户层进行操作;
  • media_entitymedia_padmedia_link等结构体的功能在上文中描述过,注意,这几个结构体会添加到media_device的链表中,同时它们结构体的开始字段都需是struct media_gobj,该结构中的mdev将会指向它所属的media_device。这种设计方便结构之间的查找;
  • media_entity中包含多个media_pad,同时media_pad又会指向它所属的media_entity
  • media_graphmedia_pipelinemedia_entity的集合,直观来理解,就是由一些模块构成的一条数据通路,由一个统一的数据结构来组织管理;

罗列一下常见的几个接口吧,细节不表了:

/*初始化entity的pads*/
intmedia_entity_pads_init(structmedia_entity*entity,u16num_pads,
structmedia_pad*pads);

/*在两个entity之间创建link*/
intmedia_create_pad_links(conststructmedia_device*mdev,
constu32source_function,
structmedia_entity*source,
constu16source_pad,
constu32sink_function,
structmedia_entity*sink,
constu16sink_pad,
u32flags,
constboolallow_both_undefined);

/*开始graph的遍历,从指定的entity开始*/
voidmedia_graph_walk_start(structmedia_graph*graph,
structmedia_entity*entity);

/*启动pipeline*/
__must_checkintmedia_pipeline_start(structmedia_entity*entity,
structmedia_pipeline*pipe);

media frameworkv4l2_devicev4l2_subdev结合起来,就可以将各个子设备构建pipeline,完美!

4. videobuf2

4.1 框架分析

  • 框架可以分成两个部分看:控制流+数据流,上文已经大概描述了控制流,数据流的部分就是video buffer了。
  • V4L2的buffer管理是通过videobuf2来完成的,它充当用户空间和驱动之间的中间层,并提供low-level,模块化的内存管理功能;

de1c1f7e-df35-11ec-ba43-dac502259ad0.png

  • 上图大体包含了videobuf2的框架;
  • vb2_queue:核心的数据结构,用于描述buffer的队列,其中struct vb2_buffer *bufs[]是存放buffer节点的数组,该数组中的成员代表了vb2 buffer,并将在queued_listdone_list两个队列中进行流转;
  • struct vb2_buf_ops:buffer的操作函数集,由驱动来实现,并由框架通过call_bufop宏来对特定的函数进行调用;
  • struct vb2_mem_ops:内存buffer分配函数接口,buffer类型分为三种:1)虚拟地址和物理地址都分散,可以通过dma-sg来完成;2)物理地址分散,虚拟地址连续,可以通过vmalloc分配;3)物理地址连续,可以通过dma-contig来完成;三种类型也vb2框架中都有实现,框架可以通过call_memop来进行调用;
  • struct vb2_ops:vb2队列操作函数集,由驱动来实现对应的接口,并在框架中通过call_vb_qop宏被调用;

4.2 流程分析

本节以omap3isp为例进行简要分析,感觉直接看图就可以了:

  1. buffer申请

de480a1c-df35-11ec-ba43-dac502259ad0.png

  1. buffer enqueue

de5f9f4c-df35-11ec-ba43-dac502259ad0.png

  1. buffer dequeue

dea9d8be-df35-11ec-ba43-dac502259ad0.png

  1. stream on

ded8a702-df35-11ec-ba43-dac502259ad0.png

行文至此,主体讲完了,相信看完本文应该有个大概的轮廓了,还有一些细节未进一步描述,就此打住。

原文标题:参考

文章出处:【微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11304

    浏览量

    209473
  • V4L2
    +关注

    关注

    0

    文章

    17

    浏览量

    3897
  • 驱动框架
    +关注

    关注

    0

    文章

    14

    浏览量

    4035

原文标题:参考

文章出处:【微信号:yikoulinux,微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Xilinx Linux 如何理解V4L2的管道驱动程序

    设备(/dev/video )控制。这两种设备,都是在视频管道(Video pipeline)驱动程序里创建的。所以,理解V4L2的管道(p
    的头像 发表于 09-30 13:44 4885次阅读
    Xilinx <b class='flag-5'>Linux</b> 如何理解<b class='flag-5'>V4L2</b>的管道<b class='flag-5'>驱动</b>程序

    Linux下摄像头应用编程

    V4L2是Video for linux2的简称,为linux中关于视频设备内核
    的头像 发表于 08-26 21:39 2903次阅读
    <b class='flag-5'>Linux</b>下摄像头应用编程

    V4L2框架概述 Xilinx视频编解码详解

    V4L2是Video for Linux2的简称,为Linux中关于视频设备内核
    的头像 发表于 09-14 10:31 9240次阅读

    V853平台Camera模块开发框架详解

    将video buffer修改为mplane方式,使用户层取图更方便 采用v4l2-event实现事件管理 采用v4l2-controls新特性 VIN框架 框架简介 VIN是全志基
    的头像 发表于 12-05 14:30 5894次阅读
    <b class='flag-5'>V</b>853平台Camera模块开发<b class='flag-5'>框架</b><b class='flag-5'>详解</b>

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

    vl42是video for Linux 2的缩写,是一套Linux内核视频设备
    的头像 发表于 11-15 09:28 1887次阅读
    深入学习<b class='flag-5'>Linux</b>摄像头<b class='flag-5'>v4l2</b>应用编程

    V4L2视频采集程序框架

    V4L2视频采集程序框架
    发表于 11-05 12:44

    [分享资料]linux设备驱动开发详解_宋宝华

    `一、看威武霸气的封面作者:宋宝华 二、读读简介,看看适合你吗?这是一本介绍Linux设备驱动开发理论、框架与实例的书,《Linux
    发表于 09-11 23:36

    Linux设备驱动开发详解:基于最新的Linux 4.0内核

    Linux设备驱动开发详解:基于最新的Linux 4.0内核
    发表于 08-31 12:29

    十天学会Linux内核驱动视频(嵌入式LINUX内核驱动进阶)

    内容简要:1.内核开发基础2.U-Boot移植3.嵌入式Linux系统构建4.内存管理子系统5.进程管理6.字符设备
    发表于 12-01 10:29

    Linux设备驱动开发详解》第4章、Linux内核模块

    Linux设备驱动开发详解》第4章、Linux内核
    发表于 10-27 14:15 0次下载
    《<b class='flag-5'>Linux</b><b class='flag-5'>设备</b><b class='flag-5'>驱动</b>开发<b class='flag-5'>详解</b>》第<b class='flag-5'>4</b>章、<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>模块

    需要了解Linux V4L2驱动架构

    video4linux2(V4L2)是Linux内核中关于视频设备的中间
    发表于 04-28 17:29 1142次阅读
    需要了解<b class='flag-5'>Linux</b> <b class='flag-5'>V4L2</b>的<b class='flag-5'>驱动</b>架构

    Linux视频设备驱动编程(v4l2编程)

    一.什么是video4linuxVideo4linux2(简称V4L2),是linux中关于视频设备
    发表于 04-02 14:35 904次阅读

    如何使用Linux内核实现USB驱动程序框架

    程序框架25.2.1 Linux内核USB驱动框架图25-2
    发表于 11-06 17:59 20次下载
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>实现USB<b class='flag-5'>驱动</b>程序<b class='flag-5'>框架</b>

    V4L2学习笔记

    1.什么是V4L2Video for(4) Linux 2 的简称,V4L的升级版。V4L2
    发表于 01-17 13:43 12次下载
    <b class='flag-5'>V4L2</b>学习笔记

    看看Linux为相机提供的驱动框架

      V4L2 (Video Linux Two),是为支持Linux内核设计的驱动框架
    的头像 发表于 08-07 16:03 3307次阅读
    看看<b class='flag-5'>Linux</b>为相机提供的<b class='flag-5'>驱动</b><b class='flag-5'>框架</b>