3. 查询视频设备属性

查询视频设备属性 学习卡片

任务目标

编写一个Linux用户空间程序,通过V4L2的VIDIOC_QUERYCAP ioctl查询指定视频设备的 capabilities,判断该设备是否为视频捕获设备(V4L2_CAP_VIDEO_CAPTURE),并输出设备名称(card)与驱动信息(driver)。

环境与依赖

  • Linux系统(内核已启用V4L2框架)
  • 开发头文件:libv4l-dev(Debian/Ubuntu)或 v4l-utils 包中的头文件
  • 编译工具:gcc
  • 测试设备:/dev/video0(若不存在,可使用 v4l2loopback 虚拟设备)

关键完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>

int main(int argc, char *argv[]) {
    const char *dev_path = (argc > 1) ? argv[1] : "/dev/video0";
    int fd = open(dev_path, O_RDWR);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    struct v4l2_capability cap;
    memset(&cap, 0, sizeof(cap));

    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
        perror("VIDIOC_QUERYCAP");
        close(fd);
        return 1;
    }

    printf("设备路径: %s\n", dev_path);
    printf("驱动名称: %s\n", cap.driver);
    printf("设备名称: %s\n", cap.card);
    printf("总线信息: %s\n", cap.bus_info);
    printf("驱动版本: %u.%u.%u\n",
           (cap.version >> 16) & 0xFF,
           (cap.version >> 8) & 0xFF,
           cap.version & 0xFF);

    printf("设备能力: 0x%08X\n", cap.capabilities);
    if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
        printf("判定结果: 是视频捕获设备\n");
    } else {
        printf("判定结果: 不是视频捕获设备\n");
    }

    close(fd);
    return 0;
}

编译与运行

# 编译
gcc -o querycap querycap.c

# 运行(默认查询 /dev/video0)
./querycap

# 指定设备
./querycap /dev/video1

验证方法

运行程序后,观察输出:

  • 若设备存在且支持V4L2,程序会打印驱动名称、设备名称、总线信息、驱动版本及设备能力值。
  • 若设备是摄像头(如USB摄像头),cap.capabilities 应包含 V4L2_CAP_VIDEO_CAPTURE(值为0x00000001),程序输出“是视频捕获设备”。
  • 若查询的是非捕获设备(如VBI设备或仅输出设备),则输出“不是视频捕获设备”。
  • 若设备路径不存在或无权限,程序会通过 perror 打印错误原因并退出。

可通过 v4l2-ctl --list-devices 命令交叉验证设备名称与驱动信息是否一致。

常见问题

  • 打开设备失败:确认设备节点存在且当前用户有读写权限(可尝试 sudo 运行)。
  • ioctl 返回错误:确认设备是V4L2设备而非其他类型(如DVB),可用 v4l2-ctl --info -d /dev/videoX 检查。
  • 无物理摄像头:安装 v4l2loopback 内核模块创建虚拟设备:sudo modprobe v4l2loopback,然后重新运行程序。