V4L2程序编写踩坑
在官镜像下用v4l2库开发摄像头软件时要主要以下几点。
1、只单独安装V4L2的开发包(如:libv4l-dev),你会发现程序怎么写都无法使用摄像头。如果你安装motion(及依赖),程序便工作正常了,这是因为安装motion时,Debian才会把V4L2其余依赖包安装好,所以安装V4L2的开发包还要装上motion,不管你用不用motion,至少V4L2这样才会正常工作(或安装好所有运行依赖,x86架构没有这个问题)。
2、V4L2头文件内的v4l2_open、v4l2_ioctl...等函数,不能与系统的open、ioctl...混用,单独使用系统的open、ioctl...兼容性更好。例如用v4l2_open打开设备,用系统ioctl设置摄像头参数等,不信的可以自己试试会有什么后果(可能会出现写坏系统分区的情况)。
3、在枚举设备的输出格式(pix_format)时会发现其可以输出很多格式,其实gc2035的输出格式能用的只有YU12、YV12、UYVY(某歪果仁测试过)。即便是个人用VIDIOC_S_FMT设置了422P,其输出的格式依旧默认是YU12,其原因在于枚举输出格式时,枚举的是sunxi-vfe设备支持的格式,枚举的过程只在sunxi-vfe内部进行,并没有跟摄像头进行实际访问操作,不是摄像头输出的格式。
4、V4L2请求内存有V4L2_MEMORY_MMAP和V4L2_MEMORY_USERPTR(另一个V4L2_MEMORY_DMABUF用于下一级设备使用,如图像转换设备等,个人还没有用过)。
但V4L2_MEMORY_USERPTR虽然VIDIOC_REQBUFS成功,但不论怎样malloc、calloc分配内存都无法VIDIOC_QBUF入队,这是因为内核Sunxi-vfe是使用Sunxi-ion管理内存(android的内存管理机制,要知道全志H5是面向Android电视盒开发出来的),如果要用V4L2_MEMORY_USERPTR,你可能要用Sunxi-ion相关用户层函数分配的内存才能VIDIOC_QBUF入队使用。
而V4L2_MEMORY_MMAP稍微好一点,摄像头拍800x600的图像还没有问题(但reqbus时count数量不能太多),但拍1600x1200就不行了,当你设置1600x1200规格后再VIDIOC_REQBUFS时,不论怎样设置都只会返回“无效参数”等错误,但你通过在终端“dmesg”查看内核日志,你会发现Sunxi-ion驱动提示无法分配内存。这是因为官方内核预留contimuousallocation内存(连续性分配内存)较小的原因,解决也很简单,只要在启动的内核的参数上加上“cma=xxxM”就可以了,把预留contimuousallocation分配多点问题就解决了,详细可到http://

linux-sunxi.org/

Kernel_arguments了解。
在V4L2_MEMORY_MMAP需增大预留的连续性分配内存,才能使用1600x1200分辨率进行拍摄,即修改boot的分区下uEnv.txt文件,”console=tty0console=ttyS0,115200n8 no_console_suspend“字段后加上cma=xxxM,设置连续性分配内存为xxxM,增大预留的连续性内存(系统默认预留96M,128M基本满足需求,图中本人分配了160M)。

图示 :把预留连续性内存加大
5、VIDIOC_DQBUF出队的v4l2_buffer,v4l2_buffer.m.offset所映射的内容只能用memcpy复制到其它地方(或用fwrite全部写进文件),且一次性访问。多次访问或把它传递到其它函数处理会引发不可料的问题,尤其在系统刚刚启动,Sunxi-vfe还没有初始化的时候问题更为突出。
6、在V4L2_MEMORY_MMAP模式下要munmap解除内存映射时,要先VIDIOC_STREAMOFF,后munmap,否则程序结束后,系统运行会出现奇怪的运行问题。