USB摄像头以其杰出的功用和低价的价格得到广泛运用。一起因其灵敏、便利的特性,易于集成到嵌入式体系中。可是假如运用现有的契合Video for Linux规范的驱动程序合作通用运用程序,难以充分利用USB带宽,帧速不高,不易满意实时监控等要求。本文首要介绍在Linux体系下USB摄像头驱动编制的一般办法,然后阐明在此基础上怎么进步帧速。
1 Linux体系中的USB摄像头驱动程序
USB设备驱动程序完全契合通用设备驱动的原则,不同的是内核供给了一些特别的API函数,便利驱动注册、毁掉自己,例如usb_reSister()和usb_dereSister();2.4版的内核还供给了关于hotplug的支撑。
1.1 USB摄像头驱动的一般编写办法
摄像头归于视频类设备。在现在的Linux中心中,视频部分的规范是Video for Linux(简称V4L)。这个规范其实界说了一套接口,内核、驱动、运用程序以这个接口为规范进行沟通。现在的V4L涵盖了视、音频流捕捉及处理等内容,USB摄像头也归于它支撑的领域。
因而,USB摄像头的驱动应当与内核供给的视频驱动挂钩。即首要在驱动中声明一个video_device结构,并为其指定文件操作函数指针数组.fops,向体系注册。在运用程序宣布文件操作的相关指令时,中心依据这些指针调用相应函数,并将该结构作为参数传递给它们。这样,就完结了驱动和中心之间的通讯。例如:
static struct video_device vdev_template={……};
//声明video_device,指出挂接驱动
static struct file_operations ov511_fops={……};
//声明本驱动的文件操作函数指针
struct video_device*vdev=video_devdata(file);
//从文件指针中提取出video_device结构
在video_device结构中,有一个私有指针priv,能够将它指向一块保存内存。在这块内存中,保存着本驱动、本设备的相关初始化信息。这块内存的恳求、初始化、指针指向等作业都是在USB驱动的枚举函数.probe中完结。这样,在枚举函数将操控权返还给体系后,因为内核不毁掉保存内存,所以驱动依然保存着自己的信息。这点与Windows体系中WDM驱动有殊途同归之处。当然,在驱动卸载函数中,应当将恳求的各块内存悉数开释。
1.2 运用双URB轮番通讯
众所周知,USBl.1总线规范界说了操控、中止、批量、等时等四种管道。关于时刻性极强可是准确度要求不高的视频捕捉运用来说,摄像头应当运用等时传输办法。为了尽或许快地得到图画数据,应当在URB中指定USB_ISO_ASAP标志。
urb->transfer_flags=USB_ISO_ASAP;//尽或许快地宣布本URB
Linux体系中任何USB传输都经过URB完结。为进步速度,能够考虑扩展URB的缓冲,这样能够下降每个USB业务中握手信息所占份额,进步有用数据的传输速度。可是受限于总线带宽和详细的USB设备芯片,单纯扩展URB的缓冲不能无限制地处理问题。详细剖析一下USB传输在操作体系中的完结:每次传输都要包括URB的树立、宣布、收回、数据收拾等阶段,这些时刻不发生有用数据。因而能够树立两个URB,在等候一个URB被收回时,也便是图画正在被传感器收集时,处理、初始化另一个URB,并在收回后马上将其宣布。两个URB替换运用,大大削减了额定时刻。作业流程如图1所示。
这个进程是在URB的完结例程中完结的,有两点需求留意:首要处理再次初始化的代码时刻不能长,不然会形成完结例程的重人,假如的确来不及,能够在完结例程中设定标志,例如“数据收集好”旗语,由运用程序运用堵塞ioctl()来查询该旗语并做处理;其次因为CPU或许会在完结例程中逗留较长时刻,体系担负较大,能够在.open函数中初始化两个URB并将其宣布,有极限地减轻体系担负。
1.3 运用双帧缓冲进步功率
Linux体系中,文件操作一般是由read、write等体系调用来完结。这些体系调用在驱动中的处理办法便是用copy_to_user()、copy_from_user()等函数在核态、户态内存空间中相互复制。可是关于大批量的图画数据,选用复制的办法显然会添加时刻开支,因而用内存映射的办法处理。首要运用vmalloc()恳求足够大的核态内存,将其作为图画数据缓冲空间,两个URB带回的图画数据在这里暂存;然后运用remap_page_range()函数将其逐页映射到用户空间中。户态的图画处理程序运用mmap()函数,直接读写核态图画缓冲内存,大大削减额定开支。
图2
图画数据的处理或许要花费比较长的时刻,不同的算法关于数据保存时刻的要求也不一样。因而能够恳求两帧图画缓冲,在处理一帧图画的一起,将两个URB带回的数据悉数填充到另一帧缓冲中,这样能够免除时刻抵触上的费事。
值得留意的是:这种办法要求时刻持有当时帧的序号、每一帧的开端地址等信息,不能将两帧图画混杂。这些信息能够保存在保存内存中,当时帧的数据收拾、序号改变在URB完结例程中完结。
2 V4L规范的改善
V4L规范现在现已发展到第二版V4L2,其基本思路与V4L相同。
2.1 规范剖析
依据V4L规范,户态程序在需求一帧图画时,CPU的走向如图2。CPU依照123456的次序完结一个循环。在这里,有一个细节被疏忽:在完结例程中,也便是图2中过程6,该URB被马上宣布,可是因为这时用户程序正在堵塞等候,没办法再次提出取得图画的恳求,因而在判别有无新恳求时,判别的成果必定是当时无恳求,导致下一个URB带回的数据被驱动丢掉;因为核态、户态的切换需求必定的时刻,加上户态多进程同步等开支,比及运用程序能够再次宣布取得一副图画的恳求时,现已有不止一个URB带回的数据被丢掉掉,这些URB包括的数据正好是新一帧图画的开端部分。因而驱动有必要比及再下一帧图画才干保存数据、缓冲。这样凭白丢失了一帧图画,帧速最少下降一半。
2.2 改善思路:不间断收集
为了处理这个问题,能够改善V4L规范作,使其添加新的功用:经过新的参数,让ioetl()函数告诉驱动不间断收集、缓冲图画数据,轮番保存在两帧缓冲区中,并在一帧图画收集好后,设定“图画收集好”旗语。户态程序只需求宣布一次“取得图画”恳求,就能够经过堵塞等候该旗语,不断取得图画。在收集完毕后,再次经过新的参数,让驱动中止缓冲即可。CPU作业流程图如图3。
图3
留意到图2、图3,两种“判别有无新恳求”的不同,即可发现新办法假定一向有恳求,因而不丢掉每个URB带回的数据,轮番保存在两个帧缓冲内。
V4L现已作为约定俗成的规范被内核支撑,因而假如运用全新的参数,作业量将适当巨大,而且不能和现有的运用程序兼容。考虑到现有的图画收集运用程序运用VIDIOCMCAPTURE作为参数,并供给帧序号,要求驱动将图画保存到指定序号的帧缓冲内。因为驱动一般只是供给几帧缓冲,因而该序号不会大于某个数字,如10。因而能够持续运用VIDIOCMCAPTURE参数,调配较大的序号来表明新增的功用,例如用10000和10001来别离表明开端和中止缓冲图画数据的要求。驱动在收到VIDIOCMCAPTURE要求后,查看这个序号。假如小于10000,则依照正常的办法处理,不然依照改善办法。这种思路能够有用处理兼容性问题。
2.3 试验成果
在赛扬366、USBl.1接口的计算机平台上,选用上述不间断收集改善V4L规范,合作双URB、双帧缓冲等办法后,帧速进步两倍有余,有用数据传输速度达960KB/s,挨近等时传输办法下USB总线的带宽极限。