2. 查询摄像头能力

任务目标

编写一个Linux用户空间程序,通过V4L2接口打开摄像头设备(如/dev/video0),查询并打印其设备能力信息,包括驱动名称、设备名称、总线信息、版本号、支持的文件格式(I/O方法)以及设备能力标志。该程序是后续所有V4L2摄像头操作(采集、设置格式等)的基础探测步骤。

环境与依赖

  • Linux系统(带V4L2内核支持,标准内核均已包含)
  • 摄像头设备节点:/dev/video0(若设备不同,通过命令行参数指定)
  • 编译器:gcc
  • 头文件:linux/videodev2.h(系统自带)、sys/ioctl.h、fcntl.h

关键完整代码

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

static void print_capability(const struct v4l2_capability *cap) {
    printf("驱动名称 (driver)     : %s\n", cap->driver);
    printf("设备名称 (card)       : %s\n", cap->card);
    printf("总线信息 (bus_info)   : %s\n", cap->bus_info);
    printf("内核版本 (version)    : %u.%u.%u\n",
           (cap->version >> 16) & 0xFF,
           (cap->version >> 8) & 0xFF,
           cap->version & 0xFF);

    printf("设备能力 (capabilities): 0x%08X\n", cap->capabilities);
    printf("  支持的文件格式:\n");
    if (cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)
        printf("    - 视频采集 (Video Capture)\n");
    if (cap->capabilities & V4L2_CAP_VIDEO_OUTPUT)
        printf("    - 视频输出 (Video Output)\n");
    if (cap->capabilities & V4L2_CAP_STREAMING)
        printf("    - 流式I/O (Streaming)\n");
    if (cap->capabilities & V4L2_CAP_READWRITE)
        printf("    - 读写I/O (Read/Write)\n");

    printf("设备专用能力 (device_caps): 0x%08X\n", cap->device_caps);
}

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("打开设备失败");
        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;
    }

    print_capability(&cap);
    close(fd);
    return 0;
}

编译与运行

# 编译
gcc -o v4l2_query_caps v4l2_query_caps.c

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

# 指定其他设备节点
./v4l2_query_caps /dev/video1

验证方法与判定标准

  1. 权限检查:若打开设备返回Permission denied,将当前用户加入video组或使用sudo运行。
  2. 成功标志:程序正常退出(exit code 0),并打印出非空的driver、card、bus_info字段。
  3. 能力字段合理性:对于标准UVC摄像头,driver通常为uvcvideo;capabilities应包含V4L2_CAP_VIDEO_CAPTURE和V4L2_CAP_STREAMING。若打印的driver为uvcvideo且包含上述标志,说明查询成功。
  4. 交叉验证:可运行系统命令v4l2-ctl --device=/dev/video0 --all(需安装v4l-utils包)对比Driver name、Card type等字段,应与本程序输出一致。

常见问题

  • ioctl返回ENOTTY:设备节点不是V4L2设备(如普通串口),确认/dev/video*路径正确。
  • 打开设备失败ENOENT:设备节点不存在,检查摄像头是否连接或驱动是否加载(ls /dev/video*)。
  • device_caps与capabilities的区别:capabilities表示设备整体能力,device_caps表示当前设备节点实际可用的能力。对大多数单节点摄像头,两者一致。