情况: 需要跑ORBSLAM, 之前一直使用USB接口的相机, 打开摄像头一般使用的是ROS下的usb-cam-node进行驱动,采集图像并发布成topic的形式,或者使用opencv的videoCapture进行图像的捕捉;
因为某些原因需要将usb接口的camera转换成mipi接口的相机; 还是使用了原先usb_cam_node进行摄像头的驱动,输入/dev/video, 对应的width和height之后,结果出现了如下的提示:
最主要的就是[ERROR], 提示如下:
[ERROR] [1608815170.494006746]: /dev/video4 is no video capture device capability is 2216693760
在usb_cam_node中找到对应的代码如下:
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
ROS_ERROR_STREAM(camera_dev_ << " is no video capture device capability is " <
这里的cap是v4l2_capability类型的变量,
struct v4l2_capability
{
u8 driver[16]; // 驱动名字
u8 card[32]; // 设备名字
u8 bus_info[32]; // 设备在系统中的位置
u32 version; // 驱动版本号
u32 capabilities; // 设备支持的操作
u32 reserved[4]; // 保留字段
};
将2216693760转换成十六进制即为: 0x84201000, 对应到v4l2_capability所表示的devide的所支持的操作分别是:
V4L2_CAP_DEVICE_CAPS
V4L2_CAP_STREAMING
V4L2_CAP_EXT_PIX_FORMAT
V4L2_CAP_VIDEO_CAPTURE_MPLANE
其中,最后一项操作的解释如下:
/* Is a video capture device that supports multiplanar formats */
#define V4L2_CAP_VIDEO_CAPTURE_MPLANE 0x00001000
而对应到usb_cam.cpp中报错部分的代码, 需要的是支持下面两种操作的设备:
V4L2_CAP_VIDEO_CAPTURE
V4L2_CAP_STREAMING
接下来对V4L2一个简单的总结:
Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版。V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛的应用。
在Linux下,所有外设都被看成一种特殊的文件,成为“设备文件”,可以象访问普通文件一样对其进行读写。一般来说,采用V4L2驱动的摄像头设备文件是/dev/video0。V4L2支持两种方式来采集图像:内存映射方式(mmap)和直接读取方式(read)。V4L2在include/linux/videodev.h文件中定义了一些重要的数据结构,在采集图像的过程中,就是通过对这些数据的操作来获得最终的图像数据。Linux系统V4L2的能力可在Linux内核编译阶段配置,默认情况下都有此开发接口。
V4L2支持内存映射方式(mmap)和直接读取方式(read)来采集数据,前者一般用于连续视频数据的采集,后者常用于静态图片数据的采集,本文重点讨论内存映射方式的视频采集。
应用程序通过V4L2接口采集视频数据分为五个步骤:
首先,打开视频设备文件,进行视频采集的参数初始化,通过V4L2接口设置视频图像的采集窗口、采集的点阵大小和格式;
其次,申请若干视频采集的帧缓冲区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据;
第三,将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集;
第四,驱动开始视频数据的采集,应用程序从视频采集输出队列取出帧缓冲区,处理完后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据;
第五,停止视频采集。
具体的程序实现流程可以参考下面的流程图:
关于usb接口的相机和MIPI接口的相机之间还有一个需要注意的区别是如下的类型:
/* Stream type-dependent parameters
*/
struct v4l2_streamparm {
__u32 type; /* enum v4l2_buf_type */
union {
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200]; /* user-defined */
} parm;
};
结构体包含两个结构体, 但是需要注意的v4l2_captureparm只能用于CAPTURE type, 而mipi接口的摄像头是不具有这种操作性的,即capability中没有这项
其对应的相关调用如下:
函数:ioctl(fd,VIDIOC_G_PARM,struct v4l2_streamparm *argp); //VIDIOC_S_PARM
作用:流相关 (如帧率)
如有疑问,欢迎交流: wx: baobaohaha_ 欢迎对SLAM有兴趣的小伙伴一起交流学习~~
参考:
V4L2对应的函数和变量详解
V4L2和MIPI接口的简要说明
V4L2学习流程分析
V4L2基础编程
V4L2官网讲解 英文
V4L2下摄像头的详细参数调整