作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习
擅长领域:驱动开发,嵌入式软件开发,BSP开发
作者主页:一个平凡而乐于分享的小比特的个人主页
文章收录专栏:IMX8MP,本专栏记录imx8mp开发板,学习开发过程中的问题及解决方法记录
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
usb摄像头应用编程
最近在京东上买了一个usb摄像头。想研究研究,应用到项目开发中。此文档记录我学习的过程。
1.V4L2简介
1.1 什么是v4l2
V4L2,即 Video for linux two ,是 Linux 内核中视频类设备的一套驱动框架,为视频类设备驱动开发和应用层提供了一套统一的接口规范使用 V4L2 设备驱动框架注册的设备会在 Linux 系统/dev/目录下生成对应的设备节点文件,设备节点的名称通常为 videoX(X为0、1、2…)
V4L2是Linux视频处理模块的最新标准代码,包括对视频输入设备的处理,如高频(即、电视信号输入端子)或摄像头,还包括视频处理输出装置。一般来说,最常见的是使用V4L2来处理相机数据采集的问题。我们通常使用的相机实际上是一个图像传感器,将捕捉到的光线通过视频芯片处理后,编码成JPG/MJPG或YUV格式输出。我们可以很容易地通过V4L2与第一台摄像机设备“通信”,如设置或获取它们的工作参数。
1.2 Video设备的V4L2框架
基于Video设备的V4L2框架
Linux系统中视频设备主要包括以下四个部分:
1.字符设备驱动程序核心:V4L2本身就是一个字符设备,具有字符设备所有的特性,暴露接口给用户空间;用户空间可以通过Ioctl系统调用控制设备;在应用层,我们可以在 /dev 目录发现 videoxx 类似的设备节点。
2.V4L2驱动核心:主要是构建一个内核中标准视频设备驱动的框架,为视频操作提供统一的接口函数;
3.平台V4L2设备驱动:在V4L2框架下,根据平台自身的特性实现与平台相关V4L2驱动部分,包括注册video_device和v4l2_dev。
4.具体的sensor驱动:主要上电、提供工作时钟、视频图像裁剪、流IO开启等,实现各种设备控制方法供上层调用并注册v4l2_subdev。
1.3 V4L2支持的设备类型
4L2支持的设备十分广泛,但是其中只有很少一部分在本质上是真正的视频设备:
video capture interface:视频采集接口,从camera上获取视频数据,视频捕获是V4L2的基本应用;
video output interface:视频输出接口,允许应用程序驱动外设提供视频图像
video overlay interface:视频覆盖接口,是捕获接口的一个变体,其工作是便于捕获设备直接显示到显示器,无需经过CPU;Android拍照应用在进行预览时,可能就是这种模式。
VBI interfaces:基于电视场消隐实现远程传送文字的技术与设备;
radio interface:无线电接口,从AM和FM调谐器设备访问音频流。
Codec Interface:编解码接口,对视频数据流执行转换。
通常情况下V4L2的主设备号是81,次设备号为0~255;这些次设备号里又分为多类设备:视频设备、Radio(收音机)设备、Teletext on VBI等。因此V4L2设备对应的文件节点有:/dev/videoX、/dev/vbiX、/dev/radioX。对于Radio设备,即用于收发声音。但要提醒注意的是,对于声音的采集与处理,在我们的Android手持设备中常会有个Mic设备,它则是属于ALSA子系统的。我们主要讨论的是Video设备。
2.V4L2-utils、ffplay工具测试usb摄像头
详细操作讲解请参考:摄像头应用测试
输入密令,录制视频
v4l2-ctl --device=/dev/video0 --set-fmt-video=width=640,height=480,pixelformat=YUYV --stream-mmap --stream-to=video100.yuv --stream-count=100
将录制得到的video100.yuv拷贝到虚拟机上,利用ffplay工具播放
ffplay -video_size 640x480 -pixel_format yuyv422 -framerate 10 -i video100.yuv
usb摄像头视频采集
说明USB摄像头工作是正常的
3. V4L2接口编程
3.1 v4l2接口编程流程
- 首先是打开摄像头设备;
- 查询设备的属性或功能;
- 设置设备的参数,譬如像素格式、 帧大小、 帧率;
- 申请帧缓冲、 内存映射;
- 帧缓冲入队;
- 开启视频采集;
- 帧缓冲出队、对采集的数据进行处理;
- 处理完后,再次将帧缓冲入队,往复;
- 结束采集。
可以看到 V4L2 的应用编程的内容并不复杂,其实就是 open,ioctl,mmap,munmap,close 这几个调用,其中只有 ioctl 的使用稍微复杂。
VIDIOC_QUERYCAP // 查询设备属性和功能
VIDIOC_ENUM_FMT // 列举数据帧格式
VIDIOC_G_FMT // 获取数据帧格式
VIDIOC_S_FMT // 设置数据帧格式
VIDIOC_REQBUFS // 申请帧缓冲区
VIDIOC_QUERYBUF // 查询帧缓冲区
VIDIOC_STREAMON // 开始视频采集
VIDIOC_DQBUF // 帧缓冲出队
VIDIOC_QBUF // 帧缓冲入队
VIDIOC_STREAMOFF // 停止视频采集
3.2 v4l2视频采集原理
通过 V4L2 采集图像之前,我们需要做的很多,但是很重要的一步是分配帧缓冲区,并将分配的帧缓冲区从内核空间映射到用户空间,然后将申请到的帧缓冲区在视频采集输入队列排队,剩下的就是等待视频数据的到来。
其具体过程为,当启动视频采集后,驱动程序开始采集一帧图像数据,会把采集的图像数据放入视频采集输入队列的第一个帧缓冲区,一阵图像数据就算采集完成了。第一个帧缓冲区存满一帧图像数据后,驱动程序将该帧缓冲区移至视频采集输出队列,等待应用程序从输出队列取出,应用程序取出图像数据可以对图像数据进行处理或存储操作,然后将帧该缓冲区放入视频采集输入队列的尾部。驱动程序接下来采集下一帧数据,放入第二个缓冲区,同样的帧缓冲区存满一帧数据后,驱动程序将该缓冲区移至视频采集输出队列,应用程序将该帧缓冲区的图像数据取出后又将该帧缓冲区放入视频输入队列尾部,这样循环往复就实现了循环采集。