V4L2 驱动架构介绍

V4L2 简介

        Video for Linux two(Video4Linux2)简称 V4L2,是 V4L 的改进版。V4L2 是 linux操作系统下用于视频和音频数据采集设备的驱动框架,为驱动和应用程序提供了一套统一的接口规范。

        在 Linux 下,所有外设都被看成一种特殊的文件,成为“设备文件”,可以象访问普通文件一样对其进行读写。采用 V4L2 驱动的摄像头设备文是/dev/videoX以及一些子设备/dev/v4l-subdevX。V4L2 支持两种方式来采集图像:内存映射方式(mmap)和直接读取方式(read)。应用层通过 open/ioctl/close 等函数来操作V4L2 设备文件的方式控制 camera 设备。

V4L2 支持的设备:

  1. Video capture device : 从摄像头等设备上获取视频数据。对很多人来讲,video capture 是 V4L2 的基本应用。设备名称为/dev/video,主设备号 81,子设备号 0~63
  2. Video output device : 将视频数据编码为模拟信号输出。与 video capture 设备名相同。
  3. Video overlay device : 将同步锁相视频数据(如 TV)转换为 VGA 信号,或者将抓取的视频数据直接存放到视频卡的显存中。
  4. Video output overlay device :也被称为 OSD(On-Screen Display)
  5. VBI device : 提供对 VBI(Vertical Blanking Interval)数据的控制,发送 VBI 数据或抓取 VBI 数据。设备名/dev/vbi0~vbi31,主设备号 81,子设备号 224~255
  6. Radio device : FM/AM 发送和接收设备。设备名/dev/radio0~radio63,主设备号81,子设备号 64~127

V4L2 架构总览

总体架构图

CRM 根设备

CRM 即 camera request manager,创建了 V4L2 根设备/dev/video0,供所有子设备注册。

V4L2 子设备

每个子设备实现特定功能,如音视频混合,编解码等。对于 camera,有如下子设备:

SENSOR, IFE, ICP, LRME, JPEG, FD, CPAS, CSIPHY, ACTUATOR, CCI, FLASH,EEPROM, OIS 等。

通过设备文件/dev/v4l-subdevX 供应用层(CSL)调用其功能。

V4L2 驱动层实现

V4L2 驱动架构

几个重要的结构体

  1. video_device:保存 V4L2 的 device node 数据。
  2. v4l2_device:表示一个 v4l2 设备,各个子设备都挂在这个结构体里面。
  3. v4l2_subdev:每个子设备都有一个实例。

Kernel V4l2 的文档:
https://www.kernel.org/doc/html/v4.9/media/kapi/v4l2-core.html

驱动主要实现的功能

  1. 具体硬件的控制代码
  2. 实现 V4L2 架构相关结构体与函数
  3. 将代码(结构体与函数)与 V4L2 框架绑定

要实现的主要结构体

struct video_device

主要的任务就是负责向内核注册字符设备。

此结构体既可以动态分配,也可以嵌入到一个更大的结构体中。

动态分配方法如下:

struct video_device *vdev = video_device_alloc();
if (vdev == NULL)return -ENOMEM;
vdev->release = video_device_release;

也可嵌入到一个大结构体中,此时要实现 release()回调:

struct video_device *vdev = &my_vdev->vdev;
vdev->release = my_vdev_release;

设置结构体主要域:

  1. v4l2_dev: 设置为 v4l2_device 父设备。
  2. name: 设置为唯一的描述性设备名。
  3. fops: 设置为已有的 v4l2_file_operations 结构体。实现文件操作。设置 .unlocked_ioctl 指向 video_ioctl2。请勿使用 .ioctl!它已被废弃。
  4. ioctl_ops: 一般设为 v4l2_ioctl_ops 来简化 ioctl 的维护。
  5. lock: 如果你要在驱动中实现所有的锁操作,则设为 NULL 。否则就要设置一个指向 struct mutex_lock 结构体的指针,这个锁将在 unlocked_ioctl 文件操作被调用前由内核获得,并在调用返回后释放。详见下一节。
  6. prio: 保持对优先级的跟踪。用于实现 VIDIOC_G/S_PRIORITY。如果设置为 NULL,则会使用 v4l2_device 中的 v4l2_prio_state 结构体。如果要对每个设备节点(组)实现独立的优先级,可以将其指向自己实现的 v4l2_prio_state 结构体。

注册视频设备:

err = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (err) {video_device_release(vdev); /* or kfree(my_vdev); */return err;
}

这个操作会创建一个字符设备

注销设备:

video_unregister_device(vdev);

这个操作将从 sysfs 中移除设备节点(导致 udev 将其从 /dev 中移除)。

struct v4l2_device

struct v4l2_device:一个硬件设备可能包含多个子设备,比如 camera 包含 sensor 设备,actuator 设备,flash 设备等。而 v4l2_device 就是所有这些设备的根节点,负责管理所有的子设备。

简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中。

注册这个设备实例:

v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);

注销 v4l2_device 使用如下函数:

v4l2_device_unregister(struct v4l2_device *v4l2_dev);

struct v4l2_subdev

struct v4l2_subdev:子设备,负责实现具体的功能。

子设备驱动可使用如下函数初始化 v4l2_subdev 结构体:

v4l2_subdev_init(sd, &ops);

向 v4l2_device 注册 v4l2_subdev:

int err = v4l2_device_register_subdev(v4l2_dev, sd);

注销子设备则可用如下函数:

v4l2_device_unregister_subdev(sd);

此后,子设备模块就可卸载,且 sd->dev == NULL。

要实现的主要函数

video_device->v4l2_file_operations

实现文件类操作,比如 open,close,read,write,mmap 等。但是 ioctl 是不需要实现的,一般都是用 video_ioctl2 代替。

                .unlocked_ioctl = video_ioctl2,

video_device->v4l2_ioctl_ops

V4L2 导出给应用层使用的所有 ioctl。只要实现需要用的,如:

v4l2_subdev->v4l2_subdev_ops 及其子函数:

        必须实现的:

                v4l2_subdev_core_ops     

        其它可按需选择,如: 

                v4l2_subdev_video_ops  

             

  

V4L2 应用层实现                       

V4L2 是一个字符设备,通过设备文件向应用层提供各种功能。应用层可以像操作普通文件一样 open/close V4L2 设备文件,而 V4L2 的大部分功能都是通过设备文件的 ioctl 导出的。

IOCTL 命令分类

功能查询相关

优先级相关

视频捕获相关

TV 视频相关

输入输出相关

控制相关

杂项

V4l2 设备的基本操作流程

  1. 打开并获取设备属性
  2. 设置帧格式
  3. 设置帧缓冲
  4. 开始进行视频流采集
  5. 停止采集关闭设备

高通平台 V4L2 架构实现

驱动层实现

驱动对应用层提供的设备节点,V4L2 相关设备文件:

其中部分子设备类型如下:

//未完待续...

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sentinel-dashboard-1.8.0.jar开机自启动脚本

启动阿里巴巴的流控组件控制面板需要运行一个jar包,通常需要运行如下命令: java -server -Xms4G -Xmx4G -Dserver.port8080 -Dcsp.sentinel.dashboard.server127.0.0.1:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &…

从Matrix-ResourceCanary看内存泄漏监控

不同于LeakCanary,在Matrix中,主要是通过Resource Canary来监控内存泄漏问题的,且监听的泄漏对象只支持Activity,官方说明如下: 结合分析LeakCanary的经验可知,要实现Activity内存泄漏监听,总体…

Unity实现设计模式——中介者模式

Unity实现设计模式——中介者模式 用一个中介者对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互。 这里使用一个生活中的例子来介绍中介者模式,比如当我们在…

Linux系统如何将新硬盘挂载到Home目录下

Linux系统如果将硬盘挂载到Home目录下 目录 1、对新增磁盘进行分区 2、分区格式化 3、将新硬盘临时挂载在一个目录下

《Reinforcement Learning: An Introduction》第8章笔记

文章目录 Chapter 8 Planning and Learning with Tabular Methods8.1 Models and Planning8.2 Dyna: Integrated Planning, Acting, and Learning8.3 When the Models Is Wrong8.4 Prioritized Sweeping8.5 Expected vs. Sample Updates8.6 Trajectory Sampling8.7 Real-time D…

EasyWindow - Android 悬浮窗框架

官网 https://github.com/getActivity/EasyWindow 项目介绍 本框架意在解决一些极端需求,如果是普通的 Toast 封装推荐使用 Toaster 集成步骤 如果你的项目 Gradle 配置是在 7.0 以下,需要在 build.gradle 文件中加入 allprojects {repositories {/…

SR800-D 5G工业路由器:将无人驾驶汽车的通信能力提升到极限

​大家好!欢迎来到今天星创易联的课堂,我是你们的通信老师,今天我们将讨论无人驾驶解决方案,其中包括SR800-D 5G工业路由器的运用。 首先,让我们聚焦于无人驾驶技术的重要性。无人驾驶汽车正在迅速崛起,这种…

多线程总结(线程池 线程安全 常见锁)

本篇文章主要是对线程池进行详解。同时引出了单例模式的线程池,也对线程安全问题进行了解释。其中包含了智能指针、STL容器、饿汉模式的线程安全。也对常见的锁:悲观锁(Pessimistic Locking)、乐观锁(Optimistic Locki…

B058-SpringBoot

目录 springboot概念与作用入门案例springboot运行方式热部署配置文件Profile多环境支持整合测试-springboot-testSpringboot-web1.返回json数据2.返回页面(模板技术)thymeleaf1.导入thymeleaf依赖2.模板文件3.controller4.启动类 SSM整合1.导包2.项目目…

私有继承和虚函数私有化能用么?

源起 以前就知道private私有化声明关键字,和virtual虚函数关键字两者并不冲突,可以同时使用。 但是,它所表示的场景没有那么明晰,也觉得难以理解,直到近段时间遇到一个具体场景。 场景 借助ACE遇到的问题进行展示 …

蓝桥杯 题库 简单 每日十题 day12

01 列名 问题描述 在Excel中,列的名称使用英文字母的组合。前26列用一个字母,依 次为A到Z,接下来2626列使用两个字母的组合,依次为AA到zz. 请问第2022列的名称是什么? 答案提交 这是一道结果填空的题,你只…

【再识C进阶3(下)】详细地认识字符分类函数,字符转换函数和内存函数

前言 💓作者简介: 加油,旭杏,目前大二,正在学习C,数据结构等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏&#x1…