V4L2系列 之 V4L2驱动框架

article/2025/9/29 17:15:02

目录

  • 前言
  • 一、V4L2驱动框架概览
    • 1、应用层 -》中间层-》驱动层
    • 2、主要代码文件(Linux 4.19版本内核)
  • 二、怎么写V4L2驱动
    • 1、如何写一个设备的驱动?
    • 2、Video设备主要结构体
    • 3、怎么写V4L2驱动
  • 三、V4L2的调试工具
    • 1、v4l2-ctl
    • 2、dev_debug
    • 3、v4l2-compliance

前言

  本篇文章主要介绍Linux内核中的V4L2框架,本篇文章所用内核版本:linux-4.19

  v4L2 (Video for Linux 2),是linux的一套视频框架,共主体位于内核,可以理解为是整个linux系统上面的视频源捕获驱动框架。其广泛应用在嵌入式设备、移动端以及个人电脑设备上面,市而上使用视频图像采集的设备如:手机、IPC、行车记录仪都会用到这个框架来进行视频采集。

  v4L2允许 应用程序 控制图像传感器以及传输格式,应用程序 借此完成拍照、预览、视频记录等图像传感器数据应用。

  之前,Linux还存在第一版的V4L2,该版本在内核2.6.38版中放弃支持。

一、V4L2驱动框架概览

1、应用层 -》中间层-》驱动层

  linux采用多层次的驱动架构来对接口进行统一与抽象,最低层次的驱动总是直接面向硬件的,而最高层次的驱动被划分为字符、块、网络设备三大类,前两类驱动在文件系统中形成类似文件的“虚拟文件”,又称为“节点node",这些节点拥有不同的名称代表不同的设备,在目录/dev下进行统一管理,系统调用函数如open、close、read等也与普通文件的操作有相似之处,这种接口的一致性是由VFS(虚拟文件系统层)抽象完成的。

  V4L2是关于视频设备的中间驱动层,向上 为 应用程序 访问 视频设备提供了通用接口,向下为设备驱动程序开发提供了统一的V4L2框架。其视频设备节点路径通常为/dev中的videoX。V4L2驱动对用户空间提供“字符设备”的形式,主设备号为81,在用户空间通过各种ioctl调用进行控制,并且可以使用mmap进行内存映射。

V4L2支持多种设备,有以下接口:
√视频采集接口(video capture interface)
√视频输出接口(video output interface)
√直接传输视频接口(video overlay interface) 
√视频间隔消隐信号接口(VBI interface)
√收音机接口(radio interface).

在这里插入图片描述

	应用通过open、ioctl等系统调用操作video设备。在内核空间,Video设备的具体操作
方法由驱动中的struct video_device提供。驱动使用video_register_device函数将struct video_device注册到V4L2的核心
层,然后V4L2的核心层再向上注册一个字符设备。这样应用就可以使用系统调用访问虚拟
文件系统中Video设备提供的方法,然后进一步访问V4L2核心层提供的v4l2_fops方法集
合,最后通过struct video_device结构休中的fops和ioctl_ops方法集合访问Video
主设备。Video主设备通过V4L2_subdev_call方法访问Video从设备,同时Video从设备可以
通过notify回调方法通知主设备发生了事件。

在这里插入图片描述

2、主要代码文件(Linux 4.19版本内核)

  v4L2的驱动源码在kernel/drivers/media/v4l2-core目录下,主要代码文件有:

(1)v4l2-dev.c //视频设备硬件的操作,包含video_device的注册、释放等,主要包括
//以下函数:videodev_initregister_chrdev_regionclass_registervideodev_exitclass_unregisterunregister_chrdev_region__video_register_devicevideo_unregister_device(2)v4l2-common.c //一些通用操作,V4l2的子设备一般是摄像头和摄像头控制器,
//它们和主机的控制操作是通过i2c总线完成的。V4l2驱动框架中跟i2c相关的代码在
//v4l2_common.c中v4l2_ctrl_query_fillv4l2_i2c_subdev_initv4l2_i2c_new_subdev_boardv4l2_i2c_new_subdevv4l2_i2c_subdev_addrv4l2_i2c_tuner_addrsv4l2_spi_subdev_initv4l2_spi_new_subdevclamp_alignv4l_bound_align_image__v4l2_find_nearest_sizev4l2_get_timestampv4l2_g_parm_capv4l2_s_parm_cap(3)v4l2-device.c //V4L2的设备支持,主要是注册v4I2_device,包括以下函数:v4l2_device_registerv4l2_device_unregisterv4l2_device_putv4l2_device_releasev4l2_device_register_subdevv4l2_device_unregister_subdevv4l2_device_register_subdev_nodesv4l2_device_release_subdev_node	(4)v4l2-ioctl.c  //处理V4L2的ioctl命令的一个通用的框架。(5)v412-subdev.c //v4l2子设备(6)v4l2-mem2mem.c //使用videobuf缓冲区的设备辅助函数。

V4L2缓冲区管理

	V4L2维护着两个缓冲队列:一个用于驱动(INPUT队列),另一个用于用户程序
(OUTPUT队列)。缓冲区(由VIDIOC_REQBUFS命令申请)被用户空间的应用程序放入驱动的队
列中(通过VIDIOC_QBUF ioctl命令)以便填充数据。驱动按顺序填充缓冲区后,
缓冲区由INPUT队列放入OUTPUT队列。当用户程序调用VIDIOC_DQBUF命令后,驱动会在OUTPUT队列中寻找可用的
缓冲,如果可用则推送到用户程序,不可用则等待直到有可用缓冲后再推送给用
户程序。缓冲区使用完后,必须调用VIDIOC_QBUF将缓冲区重新加入INPUT队列
以便再次填充数据。注意驱动程序会独立自主的填充INPUT队列中的缓冲区,如果用户程序对缓
冲数据使用不及时,INPUT队列被填满,驱动暂停等待,会产生丢帧。

二、怎么写V4L2驱动

1、如何写一个设备的驱动?

  以字符设备驱动为例,请阅读我之前所写的一篇文章:字符设备驱动的三种实现方法

2、Video设备主要结构体

  struct v4l2_device:一个硬件设备可能包含多个子设备,比如一个电视除了有capture设备,可能还有VBI设备或者FM tunner。而v4l2_device就是所有这些设备的根节点,负责管理所有的子设备。

/ * *
*struct v4l2_device -用于V4L2设备驱动程序的主结构
*
* @dev:指向设备结构体的指针。
* @mdev:指向结构体media_device的指针,可以为NULL* @subdevs:用于跟踪已注册的子设备
* @lock:锁定这个结构体;如果该结构嵌入到一个更大的结构中,驱动程序也可以使用
* 该结构。
* @name:唯一的设备名称,默认为驱动器名称+总线ID
* @notify:通知进行了某个操作(某些子设备被调用)
* @ctrl_handler:控制处理程序。可能是NULL* @prio:设备的优先级状态
* @ref:跟踪对这个结构体的引用。
* @release:当ref计数变为0时调用的释放函数。
*
* V4L2设备的每个实例都应该创建v4l2_device结构体,无论是独立的还是嵌入到
* 更大的结构体中。
*
*它允许轻松访问子设备(参见V4L2 -subdev.h),并提供基本的V4L2设备级支持。
*
* . .注意::
*
* #) @dev->driver_data指向该结构体。
* #)如果没有父设备,@dev可能是%NULL
* /
struct v4l2_device {struct device *dev;struct media_device *mdev;struct list_head subdevs;spinlock_t lock;char name[V4L2_DEVICE_NAME_SIZE];void (*notify)(struct v4l2_subdev *sd,unsigned int notification, void *arg);struct v4l2_ctrl_handler *ctrl_handler;struct v4l2_prio_state prio;struct kref ref;void (*release)(struct v4l2_device *v4l2_dev);
};

  struct video_device:这个结构体的主要作用时提供/dev/videoX或/dev/v4l-subdevx设备节点,同时对捕获接口进行抽象,用来描述一个出帧的设备。另外,Video子设备也是继承自该结构体。该结构体包含指向v4l2_file_operations、v4l2_ioctl_ops等的操作对象指针。

/ * *
* struct video_device——用于创建和管理V4L2设备节点的结构。
*
* @entity: &struct media_entity
* @intf_devnode:指向&struct media_intf_devnode的指针
* @pipe: &struct media_pipeline
* @fops:指向视频设备的&struct v4l2_file_operations的指针
* @device_caps: v4l2_capabilities中使用的设备能力
* @dev: &struct设备用于视频设备
* @cdev:字符设备
* @v4l2_dev:指向struct v4l2_device父设备的指针
* @dev_parent:指向&结构设备父设备的指针
* @ctrl_handler:与该设备节点关联的控制处理程序。可能为NULL* @queue: &struct vb2_queue与该设备节点相关联。可能为NULL* @prio:指向带有设备优先级状态的struct v4l2_prio_state的指针。
* 如果为NULL,则使用v4l2_dev->prio。
* @name:视频设备名称
* @vfl_type: V4L设备类型,由&enum vfl_devnode_type定义
* @vfl_dir: V4L接收器、发射器或m2m
* @minor:设备节点“minor”。如果注册失败,则设置为-1
* @num:视频设备节点编号
* @flags:视频设备标志。使用bitops来设置/清除/测试标志。
* 包含一组&enum v4l2_video_device_flags* @index:属性用于区分一个物理设备上的多个索引
* @fh_lock:对所有v4l2_fhs进行锁
* @fh_list: struct v4l2_fh的列表
* @dev_debug:内部设备调试标志,驱动程序不使用
* @tvnorm:支持的电视规范
*
* @release:视频设备release()回调函数
* @ioctl_ops:带有ioctl回调函数的指向&struct v4l2_ioctl_ops的指针
*
* @valid_ioctls:该设备有效的ioctl的位图
* @lock:指向& &struct mutex 序列化锁的指针
*
* . .注意::
*只有在无法从@v4l2_dev推导出@dev_parent时才设置它。
* /
* 
struct video_device
{
#if defined(CONFIG_MEDIA_CONTROLLER)struct media_entity entity;struct media_intf_devnode *intf_devnode;struct media_pipeline pipe;
#endifconst struct v4l2_file_operations *fops;u32 device_caps;/* sysfs */struct device dev;struct cdev *cdev;struct v4l2_device *v4l2_dev;struct device *dev_parent;struct v4l2_ctrl_handler *ctrl_handler;struct vb2_queue *queue;struct v4l2_prio_state *prio;/* device info */char name[32];enum vfl_devnode_type vfl_type;enum vfl_devnode_direction vfl_dir;int minor;u16 num;unsigned long flags;int index;/* V4L2 file handles */spinlock_t		fh_lock;struct list_head	fh_list;int dev_debug;v4l2_std_id tvnorms;/* callbacks */void (*release)(struct video_device *vdev);const struct v4l2_ioctl_ops *ioctl_ops;DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);struct mutex *lock;
};

3、怎么写V4L2驱动

(1)分配/设置/注册v4l2_device(调用函数注册v4l2_device_register),有辅助作用,提供自旋锁以及引用计数
(2)分配video_device:video_device_alloc()kzalloc()(3)设置video_device:.fops、.ioctl_ops、dev;
(4)注册video_device: video_register_device()参考阅读:https://blog.csdn.net/seiyaaa/article/details/120199720
Video设备注册时的执行流程可总结如下:
1.设置设备注销时资源释放回调和v4l2_device结构体。2.检查设备类型并确定设备节点基本名称。3.设置设备类型、次设备号及设备节点数量。4.将video_device结构体指针保存到全局video_device数组中。5.根据设备类型验证哪那些ioctl函数可以使用。6.分配字符设备结构体。7.设置字符设备的操作函数集合为v4l2_fops。8.将video设备注册为字符设备,并注册设备;9.设置设备引用计数为0时的回调函数,该函数主要的工作是删除注册的字符设备,
回调v4l2_device中的release函数(通常是video_device_release函数)释放
video_device结构体内存,最后减少v4l2_device的引用计数;10.增加video_device所属v4l2_device的引用计数。11.设置已注册标志V4L2_FL_REGISTERED。

Video设备访问流程

(1)首先通过系统调用访问/dev/videox用户空间设备节点。(2)进入到内核空间,访问字符设备struct file_operations中的方法。对于Video
设备,该操作集合被v4L2子系统初始化为v4l2_fops集合。(3)通过v4L2子系统提供的v4l2_fops集合,可直接调用底层驱动实现的Video主设备
struct v4l2_file_operations方法,对于ioctl方法,则需要借助中间函数
__video_do_ioctl调用底层驱动实现的struct v4l2_ioctl_ops中的ioctl功能。
struct v4l2_file_operations方法和struct v4l2_ioctl_ops方法属于主设备
方法,需要主设备的驱动实现。( 4) struct v4l2_file_operationsstruct v4l2_ioctl_ops中的函数都可以
通过v4l2_subdev_call调用video从设备struct v4l2_subdev_core_opsstruct
v4l2_subdev_video_opsstruct v4l2_subdev_pad_ops等方法,这些方法都要在
从设备驱动中实现。

三、V4L2的调试工具

1、v4l2-ctl

  为便于开发,常见的Linux发行版会附带一个v4l2-ctl的命令行工具,可以用来测试摄像头子系统。该工具可以列出系统内的设备列表,查询设备能力,调整设备属性以及设置像素格式、分辨率、帧率等,同时也可以执行捕捉图像等动作。

  参考阅读:v4l2-ctl基本使用方法

2、dev_debug

V4L2调试
由丁video系统的配置较复杂,为便于调试,V4L2提供了简单但庞大的用户空间调试手段,用于跟踪框架或用户空间API的信息。
椎架的调试信息可通过下述命令开启(通过dmesg查看):
# echo 0x3 > /sys/module/videobuf2_v4l2/parameters/debugt
# echo 0x3 > /sys/module/videobuf2_common/parameters/debugV4L2的用户空问API跟踪通过下述命令开启:
# echo 0x3 >/sys/class/video4linux/video0/dev_debug

在这里插入图片描述

3、v4l2-compliance

  Video设备要工作正常,驱动兼容性是一个重要的方面,v4l2-compliance 工具可以通过测试V4L2设备的各个方面来判断其驱动兼容性。

  使用方法请阅读:v4l-utils之v4l2-compliance

  初步了解V4L2的驱动框架后,下一篇将以《虚拟摄像头驱动:drivers\media\platform\vivid》进行详细分析解读,进一步深入理解,敬请期待.

本文内容主要来自百度百科以及韦东山老师的课程笔记,如有侵权,联系删除!欢迎各位在评论区指导交流!!!


http://chatgpt.dhexx.cn/article/4BUN2lBw.shtml

相关文章

V4L2框架概述

原文链接 本文开启 linux 内核 V4L2 框架部分的学习之旅,本文仅先对 V4L2 的框架做一个综述性的概括介绍,然后接下来的文章中会对 V4L2 框架的各个子模块进行一个全面的介绍,包括每一部分的实现原理,如何使用,用在什么…

V4l2框架分析

Table of Contents 1.V4L2框架概述 1.1 v4l2设备应用层流程 1.2 内核V4L2模块 1.2.1 video_device 1.2.2 v4l2_subdev 1.2.3 videobuf2 2. video_device结构体 2.1 图像处理模块 2.2 video_device处理流程 2.2.1 video_device 结构体成员介绍: 3. video_buf2 3.1 …

V4L2

V4L2(video 4 linux 2) V4L2有一段历史了。大约在1998的秋天,它的光芒第一次出现在Bill Dirks 的眼中。经过长足的发展,它于2002年11 月,发布2.5.46 时,融入了内核主干之中。然而直到今天,仍有一部分内核驱不支持新的A…

V4L2简介

http://work-blog.readthedocs.org/en/latest/v4l2%20intro.html 第一章 V4L2简介 1.1、什么是v4l2 V4L2(Video4Linux的缩写)是Linux下关于视频采集相关设备的驱动框架,为驱动和应用程序提供了一套统一的接口规范。 V4L2支持的设备十分广泛&…

我们一起学linux之V4L2摄像头应用流程

一、概述 Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版。V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频…

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

深入学习Linux摄像头(一)v4l2应用编程 一、什么是v4l2 二、v4l2 API介绍 2.1 Querying Capabilities 2.2 Application Priority 2.3 Device Inputs and Outputs 2.4 Video Standards 2.5 Camera Control Reference 2.6 Image Format 2.7 Cropping, compo…

V4L2驱动框架详解

1. V4L2框架概述 1.1 v4l2设备应用层流程 1.2 内核V4L2模块 2 2. video_device 2.1图像处理模块 2.2 video注册流程 3. videobuf2 3.1 与video device的关系: 3.2 buffer类型 3.3 vb2_ops回调函数 3.4 mmap 流程 4. Subdev 4.1 概念 4.2 subdev注册流程 5. media fra…

html背景自动适应,css背景图片如何自适应?

css可以使用background-size属性设置背景图片自适应,为背景图片设置background-size:cover;样式即可使背景图片自适应。 css可以使用background-size属性设置背景图片自适应。background-size属性规定背景图像的尺寸。 background-size属性: 语法&#x…

css实现图片自适应容器的几种方式

css实现图片自适应容器 经常有这样一个场景,需要让图片自适应容器的大小。 1、img标签的方式 我们马上就能想到,把width、height 设置为100%啊。来看一哈效果。 <div class=div1><img src="./peiqi.png" alt=""> </div>.div1 {widt…

css 背景图片自适应属性整理

本篇博客主要记录一些使用 css 对背景图片自适应的操作整合 背景图片取消重复 background-image: url(image.jpg); background-repeat:no-repeat;修改前 修改后 背景图片固定&#xff08;不会随着内容滚动而改变位置&#xff09; background-image: url(image.jpg); back…

CSS实现图片自适应布局

CSS实现图片自适应布局 最轻松的写法 <div class"container">// 这里图片尺寸为440X440像素&#xff0c;<img src"./images/medium.jpg" alt"test"> </div><style>.container {width: 600px;height: 600px;border: 1p…

CSS图片自适应框架

CSS图片自适应框架 使用img来设置 <!DOCTYPE html> <html><style>body{margin: 0;padding: 10px;}#a_1{display: block;width: 100px;height: 50px;overflow: hidden;padding: 10px;border: dashed;margin: 10px;}#a_1img{width: 100%;height: 100%;}</s…

css之实现图片自适应

文章目录 一、position实现图片自适应二、padding补偿法三、图片以正方形显示 原图如下&#xff1a; 在开发中&#xff0c;想在固定的高度和宽度中显示不一样的图片时&#xff0c;就会出现压缩&#xff0c;导致图片最后显示不好看&#xff0c;以下提供几种方法进行调整&#xf…

css实现图片自适应缩放的两种方法

想要实现图片根据给定宽高来自适应缩放的时候&#xff0c;会想到什么属性&#xff1f;是object-fit: cover;吗&#xff1f; 来试一试&#xff01;为了展示效果&#xff0c;我特地选了对称的图片。下面两个img元素都有一个div包裹&#xff0c;div设置固定宽高&#xff0c;第一个…

3种CSS实现背景图片全屏铺满自适应的方式

来源 | https://www.fly63.com/ 一张清晰漂亮的背景图片能给网页加分不少&#xff0c;设计师也经常会给页面的背景使用大图&#xff0c;我们既不想图片因为不同分辨率图片变形&#xff0c;也不希望当在大屏的情况下&#xff0c;背景有一块露白&#xff0c;简而言之&#xff0c;…

css怎么设置背景图片自适应大小

在css中&#xff0c;可以利用“background-size”属性设置背景图片自适应大小&#xff0c;该属性用于设置背景图片的大小&#xff0c;只需要给背景图片元素添加“background-size:cover;”样式&#xff0c;即可使背景图片的大小自适应。 本教程操作环境&#xff1a;windows10系…

CSS——图片自适应宽高

宽度拉伸&#xff1a;把width设置成100%&#xff0c;height设置auto 高度拉伸&#xff1a;把height设置成100%&#xff0c;width设置auto ​ <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv&…

使用CSS进行图片自适应的两个方法

1.object-fit 属性 设置好图片的宽高&#xff0c;然后设置object-fit属性为contain就是常见的图片自适应效果。 img {width: 400px;height: 400px;object-fit: contain;} object-fit: fill|contain|cover|scale-down|none|initial|inherit; 2.background 我们把图片作为背景…

css实现一个图片自适应,图片不会变形。

第一种&#xff0c;图片填充满容器 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" conten…

常见分布的概率分布及期望方差

文章转载&#xff1a;https://www.jianshu.com/p/c05bafb52877f 参考链接&#xff1a;https://blog.csdn.net/sodacoco/article/details/89041910