2. 查询设备能力
任务目标
编写一个Linux用户空间程序,通过 VIDIOC_QUERYCAP ioctl 查询摄像头设备(如 /dev/video0)的能力信息,解析并打印驱动名称、设备名称、驱动版本号、总线信息以及设备支持的能力标志,并判断该设备是否为视频捕获设备(V4L2_CAP_VIDEO_CAPTURE)。
环境与依赖
- Linux 系统(含 V4L2 框架,内核开启
CONFIG_VIDEO_DEV) - 摄像头设备节点
/dev/video0(或通过参数指定其他节点) - 内核头文件
linux/videodev2.h(通常由libv4l-dev或内核头文件包提供) - 编译工具:gcc
关键完整代码
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
static void print_capability_flag(__u32 flag, const char *name) {
printf(" %s\n", name);
}
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)
print_capability_flag(V4L2_CAP_VIDEO_CAPTURE, "V4L2_CAP_VIDEO_CAPTURE - 视频捕获");
if (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)
print_capability_flag(V4L2_CAP_VIDEO_OUTPUT, "V4L2_CAP_VIDEO_OUTPUT - 视频输出");
if (cap.capabilities & V4L2_CAP_STREAMING)
print_capability_flag(V4L2_CAP_STREAMING, "V4L2_CAP_STREAMING - 流式I/O");
if (cap.capabilities & V4L2_CAP_READWRITE)
print_capability_flag(V4L2_CAP_READWRITE, "V4L2_CAP_READWRITE - 读写I/O");
if (cap.capabilities & V4L2_CAP_DEVICE_CAPS)
print_capability_flag(V4L2_CAP_DEVICE_CAPS, "V4L2_CAP_DEVICE_CAPS - 设备能力");
if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
printf("\n结论: 是视频捕获设备\n");
else
printf("\n结论: 不是视频捕获设备\n");
close(fd);
return 0;
}
编译与运行
# 编译
gcc -o querycap querycap.c
# 运行(默认查询 /dev/video0)
./querycap
# 指定其他设备节点
./querycap /dev/video1
验证方法与判定标准
- 正常执行:程序能打开设备并成功调用
VIDIOC_QUERYCAP,输出驱动名、设备名、版本号等信息,无错误提示。 - 能力解析正确:输出的能力标志与
v4l2-ctl --all -d /dev/video0中Driver Info部分展示的Capabilities字段一致(若系统装有 v4l-utils)。 - 捕获判断准确:对于标准 UVC 摄像头,输出应包含
V4L2_CAP_VIDEO_CAPTURE且结论为“是视频捕获设备”;对于 TV 调谐器或视频输出设备,结论应相应变化。 - 错误路径:指定不存在的设备节点(如
/dev/video99)时,程序应报错并返回非零退出码。
常见问题
- 编译报错找不到
linux/videodev2.h:安装libv4l-dev(Debian/Ubuntu)或v4l-utils-devel(RHEL/Fedora)。 - 打开设备失败
Permission denied:将当前用户加入video组,或使用sudo运行。 - ioctl 返回
EINVAL:确认设备节点确实是 V4L2 视频设备,而非 DVB 或 radio 设备。