小工具知识网

当前位置: 首页 > 行业知识 > Linux内核V4L2架构

行业知识

Linux内核V4L2架构

2026-11-12 19:09:43 来源:互联网转载

一.V4L2简介

V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。是linux操作系统下一套用于采集图片、视频和音频数据的通用API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。 ​ V4L2支持三种方式来采集图像:内存映射方式(mmap)、直接读取方式(read)和用户指针;

二.V4L2框架

1.重要结构体
该结构体描述了视频采集设备的driver信息01 struct v4l2_capability 02 {03     __u8 driver[16];       // 驱动名字04     __u8 card[32];         // 设备名字05     __u8 bus_info[32];     // 设备在系统中的位置06     __u32 version;         // 驱动版本号07     __u32 capabilities;    // 设备支持的操作08     __u32 reserved[4];     // 保留字段09 };
该结构体描述当前camera(摄像机)支持的格式信息01 struct v4l2_fmtdesc02 {03     __u32 index;               // 要查询的格式序号,应用程序设置04     enum v4l2_buf_type type;   // 帧类型,应用程序设置05     __u32 flags;               // 是否为压缩格式06     __u8 description[32];      // 格式名称07     __u32 pixelformat;         //所支持的格式08     __u32 reserved[4];         // 保留09 };
该结构体描述每帧图像的具体格式,包括帧类型以及图像的长、宽等信息01 struct v4l2_format02 {03     enum v4l2_buf_type type;          // 帧类型,应用程序设置04     union fmt05     {06         struct v4l2_pix_format pix;   // 视频设备使用07         struct v4l2_window win;08         struct v4l2_vbi_format vbi;09         struct v4l2_sliced_vbi_format sliced;10         __u8 raw_data[200];11     };12 };
该结构体描述申请的缓冲区的基本信息01 struct v4l2_requestbuffers02 {03     __u32 count;                    // 缓冲区内缓冲帧的数目04     enum v4l2_buf_type type;        // 缓冲帧数据格式05     enum v4l2_memorymemory;         // 区别是内存映射还是用户指针方式06     __u32 reserved[2];07 };
该结构体表示一帧图像数据的基本信息,包含序号、缓冲帧长度和缓冲帧地址等信息01 struct v4l2_buffer02 {03     __u32 index;                    //buffer 序号04     enum v4l2_buf_type type;        //buffer 类型05     __u32 byteused;                 //buffer 中已使用的字节数06     __u32 flags;                    // 区分是MMAP 还是USERPTR07     enum v4l2_field field;08     struct timeval timestamp;       // 获取第一个字节时的系统时间09     struct v4l2_timecode timecode;10     __u32 sequence;                 // 队列中的序号11     enum v4l2_memory memory;        //IO 方式,被应用程序设置12     union m13     {14         __u32 offset;               // 缓冲帧地址,只对MMAP 有效15         unsigned long userptr;16     };17     __u32 length;                   // 缓冲帧长度18     __u32 input;19     __u32 reserved;20 };
2.v4l2的实现流程

 

1)Video设备又分为主设备和从设备对于Camera来说, 主设备: Camera Host控制器为主设备,负责图像数据的接收和传输, 从设备: 从设备为Camera Sensor,一般为I2C接口,可通过从设备控制Camera采集图像的行为,如图像的大小、图像的FPS等。V4L2的主设备号是81,次设备号范围0~255

2)这些次设备号又分为多类设备:

视频设备(次设备号范围0-63)

Radio(收音机)设备(次设备号范围64-127)

Teletext设备(次设备号范围192-223)

VBI设备(次设备号范围224-255)。

V4L2设备对应的设备节点有/dev/videoX、/dev/vbiX、/dev/radioX。

本文只讨论视频设备,视频设备对应的设备节点是/dev/videoX,视频设备以高频摄像头或Camera为输入源,Linux内核驱动该类设备,接收相应的视频信息并处理

2.0v4l2的分层

user space: 应用程序主要通过libv4l库来操作摄像头 也可以基于字符设备/dev/videoX自己编写应用程序 guvcview:用于调试usb摄像头(还有个软件cheese也可以) v4l2 utilities: v4l2 的工具集(参考前面第3篇文章)

kernel space: sensor、ISP、VIPP、CSI、CCI都为从设备向上,提供dev/videoX节点, 从dphy物理层获取视频数据册通过vb2子模块 CCI :主要是通过GPIO(供电、片选)、I2C(下发配置命令给sensor)实现配置sensor EHCI/OHCI:USB类型摄像头

适用于收音机,视频编解码器,视频捕获器以及视频输出设备驱动;

hardware CSIC Controller:从dphy获取mipi协议帧 I2C Controller:与sensor的i2c block通信 GPIO Controller:sensor通常需要供电或者片选

Video Control:视频处理命令(分辨率协商,数据格式处理,buffer管理)

Runtime Handle:运行时管理(Pipeline 管理,系统资源管理,中断调度)

Event Process:事件管理(上层调用,中断等事件的接收和分发);

Config Handle:配置管理(硬件拓扑结构,模组自适应列表);

external device sensror:摄像头的接口主要有:USB,DVP.MIPI(CSI)

Camera Modules:模组驱动(图像传感器,对焦电机,闪光灯等)

Camera Interfac:接口驱动(MIPI, Sub-Lvds, HiSpi, Bt656, DC等)

Image Signal Processor:图像处理驱动(基本处理模块驱动,3A统计驱动)

Video Inout Post Processor:视频输入后处理(Scaler,OSD等)

 

2.1中重要的结构体、

 

1)v4l2_device主设备

    struct v4l2_device {        struct device *dev;  // 父设备指针    #if defined(CONFIG_MEDIA_CONTROLLER)  // 多媒体设备配置选项        // 用于运行时数据流的管理,        struct media_device *mdev;    #endif        // 注册的子设备的v4l2_subdev结构体都挂载此链表中        struct list_head subdevs;        // 同步用的自旋锁        spinlock_t lock;        // 独一无二的设备名称,默认使用driver name + bus ID        char name[V4L2_DEVICE_NAME_SIZE];        // 被一些子设备回调的通知函数,但这个设置与子设备相关。子设备支持的任何通知必须在        // include/media/.h 中定义一个消息头。        void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg);        // 提供子设备(主要是video和ISP设备)在用户空间的特效操作接口,        // 比如改变输出图像的亮度、对比度、饱和度等等        struct v4l2_ctrl_handler *ctrl_handler;        // 设备优先级状态        struct v4l2_prio_state prio;        /* BKL replacement mutex. Temporary solution only. */        struct mutex ioctl_lock;        // struct v4l2_device结构体的引用计数,等于0时才释放        struct kref ref;        // 引用计数ref为0时,调用release函数进行释放资源和清理工作        void (*release)(struct v4l2_device *v4l2_dev);    };

由上图可以知道v4l2_device是v4l2子系统的入口,管理v4l2zi系统的主设备和从设备。简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中以提供v4l2框架的功能,比如struct isp_device

2)video_device

struct video_device{    const struct v4l2_file_operations *fops;    struct cdev *cdev;     //vdev->cdev->ops = &v4l2_fops;  字符设备描述符    struct v4l2_device *v4l2_dev;    struct v4l2_ctrl_handler *ctrl_handler;​    struct vb2_queue *queue;  //q->ops = &dmarx_vb2_ops; buf操作真正驱动回调函数  …………    const struct v4l2_ioctl_ops *ioctl_ops;//vdev->ioctl_ops = &rkisp_dmarx_ioctl;   …………};

V4L2子系统使用v4l2_device结构体管理设备,设备的具体操作方法根据设备类型决定,

前面说过管理的设备分为很多种,

若是视频设备,则需要注册video_device结构体,并提供相应的操作方法。

对于视频设备Camera而言,Camera控制器可以视为主设备,接在Camera控制器上的摄像头可以视为从设备。

3) v4l2_subdev从设备

 [include/media/v4l2-subdev.h]    #define V4L2_SUBDEV_FL_IS_I2C        (1U    Multimedia support --->      [*] V4L platform devices --->           STM32 Digital Camera Memory Interface (DCMI) support       I2C Encoders, decoders, sensors and other helper chips --->           OmniVision OV5640 sensor support

四.用ffmpeg测试

4.1添加ffmpeg

利用buildroot-2021.02.1添加ffmpeg

 

选中alsa-utils和ffmpeg之后进入ffmpeg

 

选中自己需要用到的库。之后sudo make,考备至开发板。

4.2视频测试

执行以下命令测试录制视频

ffmpeg -f v4l2 -framerate 10 -i /dev/video1 -q 10 my.mp4

4.3搭建nginx-rtmp服务器进行推流拉流测试

安装以下依赖

 

创建文件夹存放nginx

mkdir rtmpcd rtmpwget http://nginx.org/download/nginx-1.13.3.tar.gz

去github下载nginx-rtmp模块

git clone https://github.com/arut/nginx-rtmp-module.gittar -zxvf nginx-1.13.3.tar.gzcd nginx-1.13.3./configure --add-module=../nginx-rtmp-modulemakemake install

由于版本nginx版本不同,这里不一定能编译通过。

没报错的话,会有如下目录

/usr/local/nginx

cd /usr/local/nginxcd sbin

启动nginx ./nginx 启动niginx时也可能出现错误,如下:

asdf@ubuntu:/usr/local/nginx/sbin$ ./nginxnginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (13: Permission denied)2021/07/07 07:39:22 [emerg] 23751#0: mkdir() "/usr/local/nginx/client_body_temp" failed (13: Permission denied)

此时需要修改权限

sudo chown root nginx sudo chmod u+s nginx

查看进程

ps -ef|grep nginx

ifconfig 查看ip,浏览器访问ip,看到下图, 说明nginx安装ok.

 

注意:这是动态ip, 每次开机启动都不同,如果推流失败可能是ip变动了。 配置rtmp服务 配置文件修改, cd到nginx的conf目录 vim nginx.conf 添加如下内容

 

重启nginx pkill nginx

重启./nginx

推本地流测试 ffmpeg -re -i 1.mp4 -f flv rtmp://192.168.126.132/live

实时推流测试

ffmpeg -f v4l2 -framerate 15 -i /dev/video0 -q 15 -f flv rtmp://192.168.126.132/live

下载VLC软件

VLC播放测试

上一篇:MT破解版背后的犯罪真相揭秘,法律红线绝不可逾越!

下一篇:庄园挖矿机秘籍,轻松掌握挖矿技巧,开启财富之门!