一、vivi.c分析
1、vivi.c是Linux中虚拟的v4l2驱动,使用它来学习v4l2驱动架构
1.vivi驱动涉及文件:
vivi.c 驱动的具体实现
v4l2-common.c
V4L2-dev.c video_register_device(struct video_device *vdev...);
V4L2-device.c v4l2_device_register(struct device *dev,struct v4l2_device *v4l2_device);
videobuf_core.c
videobuf_vmalloc.c
2.主要关注以下几个结构体:
struct video_device 视频类设备的基类,另外字符设备驱动的基类为cdev,所有的操作都是围绕cdev结构体
struct v4l2_file_operations 包含vivi_read,vivi_open等函数具体实现。在系统调用的时候,会首先调用cdev的file_operations的v4l2_read,v4l2_open等函数,在这些函数中会使用struct file中的video_device来调用vivi_read等函数具体去实现。
struct v4l2_ioctl_ops ioctl操作的函数的具体实现
struct V4l2_device
struct videobuf_buffer 视频数据缓冲区,对应一帧视频,里面包含视频的大小等信息
struct videobuf_queue 视频缓冲区队列
以上几个结构体可能不会被单独使用,一般都被包含在某个更大的对象结构中,比如video_device和v4l2_device都包含在vivi_dev中,而vivi_dev被包含在viv_fh中,videobuf_buffer被包含在vivi_buffer中。
这个struct file_opertions v4l2_fops是字符设备给上层提供的系统调用,这里的函数最终调用的还是struct v4l2_file_operations (vivi_fops)的实现,可以查看v4l2_open的实现。videobuf_queue_ops中实现了缓冲队列的一些操作,buffer_setup,buffer_prepare,buffer_queue,buffer_release等,但是这些申请的缓冲队列都是在内核空间,在vivi_mmap函数中videobuf_mmap_mapper(struct videobuf_queue *q,struct vm_area_struct *vma);将缓冲队列映射到vm_area_struct虚拟地址
3.分析程序流程:
在vivi.c文件中
vivi_create_instance()
v4l2_device_register()
给video_device vdev对象赋值v4l2_file_operations和v4l2_ioctl_ops等
video_device_register()
初始化video_device对象vdev
初始化video_device中的cdev结构体
cdev_add()注册字符设备
初始化video_device中struct device结构体
device_register()在/dev/目录下创建设备节点
v4l2_dev.c文件里file_operations中的v4l2_ioctl最终调用的还是vivi.c文件里v4l2_file_operations中的video_ioctl2函数,但是这里的video_ioctl2不像vivi_open,vivi_read等是具体的实现,video_ioctl2具体的实现已经单独拿出来放到v4l2_ioctl.c文件中了,所以video_ioctl2最终调用的是v4l2_ioctl.c文件中的__video_do_ioctl(file,cmd,arg)函数,而__video_do_ioctl(file,cmd,arg)函数又回过来调用vivi_ioctl中vivi_ioctl_ops中的函数。
二、V4L2架构分析
v4l2向上为应用程序提供了统一的调用接口,向下为设备驱动程序提供了统一的V4L2框架;Linux中V4L2驱动的视频设备(如摄像头、视频采集卡)的设备文件为/dev/videoX,主设备号81,对于视频设备次设备号为0-63(是字符设备),Radio设备为64-127,Teltext设备为192-223,VBI设备是224-255,V4L2驱动的视频设备在用户空间通过ioctl()控制,还可以进行mmap()映射。
要想了解 V4l2 有几个重要的文档是必须要读的:
1、源码Documentation/video4linux目录下的V4L2-framework.txt和videobuf
2、V4L2的官方API文档V4L2 API Specification
3、源码drivers/media/video目录下的sample程序vivi.c(虚拟视频驱动程序,此代码模拟一个真正的视频设备V4L2 API)。
V4l2可以支持多种设备,它可以有以下几种接口:
1. 视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.
2. 视频输出接口(video output interface):可以驱动计算机的外围视频图像设备--像可以输出电视信号格式的设备.
3. 直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU.
4. 视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号.
5. 收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流.
V4L2 驱动核心
V4L2 的驱动源码在drivers/media/video目录下,主要核心代码有:
v4l2-dev.c //linux版本2视频捕捉接口,主要结构体 video_device 的注册 v4l2-common.c //在Linux操作系统体系采用低级别的操作一套设备structures/vectors的通用视频设备接口。 //此文件将替换videodev.c的文件配备常规的内核分配。 v4l2-device.c //V4L2的设备支持。注册v4l2_device v4l22-ioctl.c //处理V4L2的ioctl命令的一个通用的框架。 v4l2-subdev.c //v4l2子设备 v4l2-mem2mem.c //内存到内存为Linux和videobuf视频设备的框架。设备的辅助函数,使用其源和目的地videobuf缓冲区。 头文件linux/videodev2.h、media/v4l2-common.h、media/v4l2-device.h、media/v4l2-ioctl.h、media/v4l2-dev.h、media/v4l2-ioctl.h等。
来源:http://zjbintsystem.blog.51cto.com/964211/464729 http://www.rosoo.net/a/201001/8382.html (此二者类似)
open(CAPTURE_DEVICE, O_RDWR | O_NONBLOCK, 0))关于阻塞模式和非阻塞模式,应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
参考:http://blog.csdn.net/luckywang1103/article/details/17406029
关于如何创建设备节点的:用户空间的udev会根据device_create创建相应的设备节点;这里只是简单说说我的理解class_create与class_register功能上类似,只是class_register需要分配struct class对象内存并初始化。自动创建设备节点class_create与device_create或者class_register,device_register,用户空间的udev会根据device_create创建相应的设备节点
linux中class_create和class_register说明:http://www.cnblogs.com/skywang12345/archive/2013/05/15/driver_class.html (未看)
v4l2驱动架构解析与开发引导: http://www.360doc.com/content/13/1010/16/7775902_320343471.shtml