USB摄像头在Linux下的使用

747 阅读4分钟

寻找摄像头设备点

  1. 检查设备文件列表: 在开发板上插上摄像头,打开终端,运行以下命令来列出所有当前的V4L2(video for linux 2)设备文件:

    ls /dev/video*
    

    这个命令会列出所有当前存在的视频设备文件,例如/dev/video0/dev/video1等。

  2. 检查摄像头是否被系统识别: 插入摄像头后,运行ls命令再次检查/dev/video*目录,看是否有新的设备文件出现。如果有,这通常意味着摄像头已被系统识别

  3. 再次执行ls /dev/video*命令后,发现/dev/video0已经不再列出,而其他设备文件的编号依次向前移动了一个位置。

根据这些信息,我们可以合理推测,当摄像头被拔出时,/dev/video0消失了,其他设备文件的编号向前移动。这意味着摄像头很可能是/dev/video0。当摄像头被重新插入时,它应该会重新出现在/dev/video0的位置。所以设备点是/dev/video0

根据设备点编程查看摄像头属性

int main() {
    // 打开摄像头设备文件,以读写模式(O_RDWR)
    int fd = open("/dev/video0", O_RDWR);
    // 如果打开失败,打印错误信息并返回错误码
    if (fd < 0) {
        perror("打开设备失败!");
        return -1;
    }

    // 定义一个结构体用于存储视频格式描述信息
    struct v4l2_fmtdesc v4fmt;
    // 设置结构体的type字段,指定查询的视频捕获类型
    v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    // 初始化格式索引计数器
    int i = 0;
    // 使用无限循环来枚举所有支持的视频格式
    while (1) {
        // 设置要查询的格式的索引
        v4fmt.index = i;
        // 通过ioctl系统调用来获取当前索引的视频格式描述
        int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt);
        // 如果ioctl调用失败,根据errno判断失败原因
        if (ret < 0) {
            // 如果errno为EINVAL,表示已经枚举完所有格式,打印提示信息并退出循环
            if (errno == EINVAL) {
                printf("已经枚举完所有支持的格式。\n");
                break;
            }
            // 如果errno不是EINVAL,打印错误信息并退出循环
            perror("ioctl调用失败");
            break;
        }
        // 打印当前查询到的视频格式的索引
        printf("index=%d\n", v4fmt.index);
        // 打印格式的属性标志
        printf("flags=%d\n", v4fmt.flags);
        // 打印格式的描述信息
        printf("description=%s\n", v4fmt.description);
        // 打印格式的像素格式值,以十六进制形式
        printf("pixelformat=%08x\n", v4fmt.pixelformat);
        // 打印格式描述结构体中的保留字段
        printf("reserved=%d\n", v4fmt.reserved[0]);
        // 递增索引计数器,为下一次循环准备
        i++;
    }

    // 关闭设备文件描述符,释放资源
    close(fd);

    // 程序正常退出,返回0
    return 0;}

在终端上运行结果如下图所示

6a4c0449abde70b0c5c91dc49921781.png

运行结果提供了有关摄像头支持的视频格式之一的详细信息。下面是输出结果的每一行的解释:

  1. index=0:这表示当前列出的是第一个支持的视频格式。
  2. flags=1flags 字段包含了关于视频格式的属性。具体的标志定义可以在 <linux/videodev2.h> 头文件中找到,但通常 1(即 V4L2_FMT_FLAG_COMPRESSED)表示该格式是压缩格式。JPEG 就是一种常见的压缩图像格式。
  3. description=JPEG:这表明摄像头支持 JPEG 格式。JPEG 是一种广泛使用的图像压缩标准,通常用于照片和网络图像。
  4. pixelformat=4745504a:这是 JPEG 格式的像素格式编码。在 V4L2 API 中,像素格式通常用一个四字节的值表示,这里 4745504a 对应于 ASCII 码中的 "JPEG"。前两个字节 "47 45" 表示 "GE",后两个字节 "50 4a" 表示 "PJ",合起来就是 "JPEG"。
  5. reserved=0reserved 字段用于将来的扩展,目前没有使用,所以它的值是0。

内置的摄像头需要考虑

当你执行 lsmod | grep uvcvideo 命令并且没有任何输出时,这可能意味着 uvcvideo 内核模块没有被加载。uvcvideo 是Linux内核中的一个模块,用于支持USB视频类(UVC)设备,这包括大多数USB摄像头。

以下是一些步骤来解决这个问题:

  1. 手动加载模块: 尝试手动加载 uvcvideo 模块:

    sudo modprobe uvcvideo
    
  2. 检查模块是否加载: 再次运行 lsmod | grep uvcvideo 来检查模块是否成功加载。

  3. 检查错误日志: 如果手动加载模块后仍然没有输出,查看 dmesg 的输出来获取可能的错误信息:

    dmesg | tail
    
注意要和主机相连接才能用

image.png