一文分析Linux v4l2框架

news2024/11/26 3:25:40

说明:

  1. Kernel版本:4.14

  2. ARM64处理器,Contex-A53,双核

  3. 使用工具:Source Insight 3.5, Visio

1. 概述

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

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

开始吧。

2. v4l2-core

2.1 应用视角

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

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

  1. 打开设备文件/dev/videoX;

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

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

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

  5. 开始视频流采集工作;

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

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

  • 通常一个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等;

  • 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 流程分析

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

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

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

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

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

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

3. media framework

3.1 问题引入

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

  • CSI:camera接口,接收图像数据,RGB/YUV/JPEG等;

  • CCDC:视频处理前端,CCDC为图像传感器和数字视频源提供接口,并处理图像数据;

  • Preview/Resizer:视频处理后端,Preview提供预览功能,可针对不同类型的传感器进行定制,Resizer提供将输入图像数据按所需的显示或视频编码分辨率调整大小的方法;

  • H3A/HIST:静态统计模块,H3A支持AF、AWB、AE的回路控制,HIST根据输入数据,提供各种3A算法所需的统计数据;

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

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

  • Raw RGB数据进入ISP模块后,可以在运行过程中,根据实际的需求进行通路设置;

  • 所以,重点是:它需要动态设置路径!

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

3.2 框架

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

  • 模块之间相互独立,通过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的驱动中,数据流就如下图所示:

  • video devnode代表video device,也就是前文中提到的导出到用户空间的节点,用于与用户进行控制及数据交互;

  • 每个模块分别有source pad和sink pad,从连接图就可以看出,数据通路灵活多变;

  • 至于数据通路选择问题,可以在驱动初始化的时候进行链接创建,比如isp_create_links;

还是看一下数据结构吧:

  • media_device:与v4l2_device类似,也是负责将各个子模块集中进行管理,同时在注册的时候,会向系统注册设备节点,方便用户层进行操作;

  • media_entity、media_pad、media_link等结构体的功能在上文中描述过,注意,这几个结构体会添加到media_device的链表中,同时它们结构体的开始字段都需是struct media_gobj,该结构中的mdev将会指向它所属的media_device。这种设计方便结构之间的查找;

  • media_entity中包含多个media_pad,同时media_pad又会指向它所属的media_entity;

  • media_graph和media_pipeline是media_entity的集合,直观来理解,就是由一些模块构成的一条数据通路,由一个统一的数据结构来组织管理;

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

/* 初始化entity的pads */
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
        struct media_pad *pads);

/* 在两个entity之间创建link */
int media_create_pad_links(const struct media_device *mdev,
      const u32 source_function,
      struct media_entity *source,
      const u16 source_pad,
      const u32 sink_function,
      struct media_entity *sink,
      const u16 sink_pad,
      u32 flags,
      const bool allow_both_undefined);

/* 开始graph的遍历,从指定的entity开始 */
void media_graph_walk_start(struct media_graph *graph,
       struct media_entity *entity);

/* 启动pipeline */
__must_check int media_pipeline_start(struct media_entity *entity,
          struct media_pipeline *pipe);

将media framework和v4l2_device及v4l2_subdev结合起来,就可以将各个子设备构建pipeline,完美!

4. videobuf2

4.1 框架分析

  • 框架可以分成两个部分看:控制流+数据流,上文已经大概描述了控制流,数据流的部分就是video buffer了。

  • V4L2的buffer管理是通过videobuf2来完成的,它充当用户空间和驱动之间的中间层,并提供low-level,模块化的内存管理功能;

  • 上图大体包含了videobuf2的框架;

  • vb2_queue:核心的数据结构,用于描述buffer的队列,其中struct vb2_buffer *bufs[]是存放buffer节点的数组,该数组中的成员代表了vb2 buffer,并将在queued_list和done_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为例进行简要分析,感觉直接看图就可以了:

buffer申请

buffer enqueue

buffer dequeue

stream on

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/403191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Transformer-XL:打破序列长度限制的Transformer模型

❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…

Redis经典五种数据类型底层实现原理解析

目录总纲redis的k,v键值对新的三大类型五种经典数据类型redisObject结构图示结构讲解数据类型与数据结构关系图示string数据类型三大编码格式SDS详解代码结构为什么要重新设计源码解析三大编码格式hash数据类型ziplist和hashtable编码格式ziplist详解结构剖析ziplist的优势(为什…

TypeScript 基础学习之泛型和 extends 关键字

越来越多的团队开始使用 TS 写工程项目, TS 的优缺点也不在此赘述,相信大家都听的很多了。平时对 TS 说了解,仔细思考了解的也不深,借机重新看了 TS 文档,边学习边分享,提升对 TS 的认知的同时,…

Qt静态扫描(命令行操作)

Qt静态扫描(命令行操作) 前沿: 静态代码分析是指无需运行被测代码,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌…

Linux查看UTC时间

先了解一下几个时间概念。 GMT时间:Greenwich Mean Time,格林尼治平时,又称格林尼治平均时间或格林尼治标准时间。是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间。 GMT时间存在较大误差,因此不再被作为标准时间使用。现在…

数据传输服务DTS的应用场景(阿里巴巴)

数据传输服务DTS的应用场景(阿里巴巴) 数据传输服务DTS(Data Transmission Service)支持数据迁移、数据订阅和数据实时同步功能,帮助您实现多种典型应用场景。 不停机迁移数据库 传输方式:数据迁移 为了保证数据的一致性&#…

【17】组合逻辑 - VL17/VL19/VL20 用3-8译码器 或 4选1多路选择器 实现逻辑函数

VL17 用3-8译码器实现全减器 【本题我的也是绝境】 因为把握到了题目的本质要求【用3-8译码器】来实现全减器。 其实我对全减器也是不大清楚,但是仿照对全加器的理解,全减器就是低位不够减来自低位的借位 和 本单元位不够减向后面一位索要的借位。如此而已,也没有很难理解…

Python3简单实现图像风格迁移

导语T_T之前似乎发过类似的文章,那时候是用Keras实现的,现在用的PyTorch,而且那时候发的内容感觉有些水,于是我决定。。。好吧我确实只是为了写点PyTorch练手然后顺便过来水一篇美文~~~利用Python实现图像风格的迁移!&…

Python实现性能测试(locust)

一、安装locustpip install locust -- 安装(在pycharm里面安装或cmd命令行安装都可)locust -V -- 查看版本,显示了就证明安装成功了或者直接在Pycharm中安装locust:搜索locust并点击安装,其他的第三方包也可以通过这种方式二、loc…

JavaScript Math(算数)对象

Math(算数)对象的作用是:执行常见的算数任务。在线实例round()如何使用 round()。random()如何使用 random() 来返回 0 到 1 之间的随机数。max()如何使用 max() 来返回两个给定的数中的较大的数。(在 ECMASCript v3 之前&#xf…

站外seo优化有用吗?值得投入时间和精力吗?

随着互联网的普及和竞争的激烈化,SEO(Search Engine Optimization,搜索引擎优化)已经成为各种网站推广的必备技能。 而站外SEO优化就是指通过在其他网站上增加链接和引用等方式,来提高自己网站的搜索引擎排名和曝光度…

【6G 新技术】6G数据面介绍

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…

window.onresize的详细使用

最近做的项目老是涉及到大小屏切换,但是因为屏幕宽高不一样的原因,老是要计算表格高度 window.onresize:监听window窗口变化,当窗口大小发生变化时,会触发此事件 含义 MDN中的定义是这样子的: 文档视图调…

GitHub与PicGo搭建免费稳定图床并实现Typora内复制自动上传

本文介绍基于Github平台与PicGo工具,构建免费、稳定的图床,并实现在Typora内撰写Markdown文档时,粘贴图片就可以将这一图片自动上传到搭建好的图床中的方法。 1 配置GitHub 首先,我们需要配置Github,创建一个仓库从而…

mysql 查询一个表的数据,并修改部分数据,再插回原来的表中,复制某个用户的数据给另一个用户

mysql 查询一个表的数据,并修改部分数据,再插回原来的表中,复制某个用户的数据给另一个用户 一、需求 我有一表日记的表,表中盛放着所有用户的日记数据。 在做演示项目的时候,我需要将一个用户的数据复制给另一个用户…

PlotNeuralNet + ChatGPT创建专业的神经网络的可视化图形

PlotNeuralNet:可以创建任何神经网络的可视化图表,并且这个LaTeX包有Python接口,我们可以方便的调用。 但是他的最大问题是需要我们手动的编写网络的结构,这是一个很麻烦的事情,这时 ChatGPT 就出来了,它可…

JavaScript学习笔记(3.0)

数组是一种特殊类型的对象。在JavaScript中对数组使用typeof运算符会返回“object”。 但是&#xff0c;JavaScript数组最好以数组来描述。 数组使用数字来访问其“元素”。比如person[0]访问person数组中的第一个元素。 <!DOCTYPE html> <html> <body>&l…

【JavaEE进阶】——第一节.Maven国内源配置

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 操作步骤 1.打开项目配置界面&#xff08;当前项目配置&#xff09; 2.检查并配置国内源 3.再次打开项目配置界面&#xff08;新项目配置&#xff09; 4…

Android RecyclerView的notify方法和动画的刷新详解

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 前言&#xff1a; 本篇讲解了RecyclerView关于通知列表刷新的常用的notify方法。和Recy…

综合练习7 摄氏度转华氏温度(“\t“的使用,循环语句)

综合练习7 摄氏度转华氏温度 使用do…while循环&#xff0c;在控制台输入摄氏温度与华氏温度的对照表。 对照表从摄氏温度-30℃到50℃&#xff0c;每行间隔10℃&#xff0c;运行如下&#xff1a; 摄氏温度&#xff1a;-30℃ 华氏温度&#xff1a;-22.0℉ 摄氏温度&#xff1a;…