CSDN仅用于增加百度收录权重,排版未优化,日常不维护。请访问:www.hceng.cn 查看、评论。
本博文对应地址: https://hceng.cn/2018/03/08/Linux摄像头驱动1——vivid/#more
Linux摄像头驱动学习第一篇,对虚拟视频驱动Virtual Video Driver(vivid)进行测试、分析、编写。
V4L2(Video for Linux two)是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口。
V4L2可以支持多种设备,它可以有以下几种接口:
- Video capture interface(视频采集接口):从摄像头等设备上获取视频数据,是V4L2设计最初功能;
- Video output interface(视频输出接口):驱动计算机的外围视频、图像显示设备;
- Video overlay interface(直接传输视频接口):把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过CPU;
- Video output overlay device(视频输出覆盖设备):也被称为OSD(On-Screen Display),即在显示画面上叠加一层显示,比如菜单设置界面;
- VBI interface(视频间隔消隐信号接口):提供对VBI(Vertical Blanking Interval)数据的控制,它可以使应用可以访问传输消隐期的视频信号;
- Radio interface(收音机接口):处理从AM或FM高频头设备接收来的音频流;
1.V4L2框架分析
2.测试vivid
这里目的先加载vivid驱动,然后运行应用程序调用vivid驱动,初步体验效果。
2.1加载驱动
先在Ubuntu16.04上输入uname -a
,可以得到当前Ubuntu内核版本号:
Linux ubuntu 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
当前内核版本是4.4.0-116-generic
,然后去Linux内核官网下载对应的内核,提取出其中的linux-4.13.9/drivers/media/
文件夹。
修改media/platform/vivid/
下的Makefile
:
KERN_DIR = /usr/src/linux-headers-4.4.0-116-generic
vivid-objs := vivid-core.o vivid-ctrls.o vivid-vid-common.o vivid-vbi-gen.o \
vivid-vid-cap.o vivid-vid-out.o vivid-kthread-cap.o vivid-kthread-out.o \
vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \
vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \
vivid-osd.o vivid-tpg.o vivid-tpg-colors.o
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-$(CONFIG_VIDEO_VIVID) += vivid.o
然后执行make
编译,获得vivid.ko
此时加载模块sudo insmod vivid.ko
,发现报错如下:
insmod: ERROR: could not insert module vivid.ko: Unknown symbol in module
原因是模块中的一些依赖函数的模块,没有加载,通过dmesg
命令,可以看到很多函数:
[ 488.786285] vivid: Unknown symbol vb2_queue_init (err 0)
[ 488.786295] vivid: Unknown symbol v4l2_ctrl_poll (err 0)
[ 488.786304] vivid: Unknown symbol v4l2_enum_dv_timings_cap (err 0)
[ 488.786314] vivid: Unknown symbol video_ioctl2 (err 0)
[ 488.786364] vivid: Unknown symbol v4l2_get_timestamp (err 0)
[ 488.786389] vivid: Unknown symbol v4l2_device_put (err 0)
[ 488.786418] vivid: Unknown symbol vb2_ioctl_streamoff (err 0)
…………
需要先加载这些函数所在的模块才行。
这里有两个方法:
一是找到函数对应的文件,修改Makefile
,编译出来,先加载。
二是找到函数对应的文件,其实模块都已经编译好了,路径在/lib/modules/4.4.0-116-generic/kernel/drivers/media/v4l2-core/
里面,直接加载即可。
这两种方式都需要慢慢找对应的文件,比较麻烦,直接:
sudo modprobe vivid //安装自带vivid及依赖
sudo rmmod vivid //卸载自带的vivid
sudo insmod ./vivid.ko //安装自己编译的vivid.ko
这里先使用modprobr
加载vivid,会将其依赖一并加载,然后再卸载vivid,最后加载上我们编译的vivid.ko
。
这里为什么使用自己编译的vivid.ko
,而不使用自带的?
因为后面修改vivid源码后,重新加载修改后的驱动,才知道修改后的效果。
2.2应用程序
Linux摄像头测试软件webcam、spcaview、luvcview、xawtv等,经测试,luvcview
和xawtv
比较靠谱。
luvcview -h //帮助信息
luvcview -d /dev/videoX //指定设备
luvcview -L //查询当前摄像头所支持的所有数据格式以及分辨率信息
luvcview //运行摄像头
xawtv -h //帮助信息
xawtv -c /dev/videoX //指定设备
xawtv -noalsa //关闭声卡启动
xawtv //运行摄像头
这里加载vivid驱动后,运行xawtv效果如下:
3.分析vivid
第一次接触V4L2,直接对内核提供的Virtual Video Driver(vivid)进行分析,只要熟悉了vivid,后续再对摄像头再进行分析,就会轻松很多。
vivid是内核提供的一个虚拟机的视频设备驱动,内核提供的vivid源码在linux-4.13.9/drivers/media/platform/vivid/
。
3.1 初始化、注册分析
在vivid_init()
里分别注册了vivid_pdev
和vivid_pdrv
,注册后,由于两者name
一致,则会调用probe()
。在probe()
里面主要进行初始化、注册等相关流程。
可以看到,在probe()
里,会调用vivid_create_instance()
,让后在里面先分配一个video_device
,然后设置video_device
,包括操作函数ops
,ioctl
操作函数,设备等。
然后对ctrl
属性进行详细的设置,最后注册video_device
,和进行常规的字符设备注册。
因此,写摄像头驱动程序的流程如下:
- 分配
video_device
:video_device_alloc()
或kzalloc()
;
- 设置
video_device
:.fops
、.ioctl_ops
、dev
; - 注册
video_device
:video_register_device()
;
3.2 操作函数分析
再来看看操作函数是如何调用的:
当应用层open()
/read()
/write()
操作/dev/videox