所以我需要的很简单 - 当前可用的视频捕获设备(网络摄像头)的列表。我需要它在简单的 C 或 C++ 控制台应用程序中。我所说的列表是指类似控制台输出的内容:
1) Asus Web Camera
2) Sony Web Camera
所以这看起来很简单,但我有一个要求 - 尽可能多地使用本机操作系统 api - 没有外部库 - 毕竟 - 我们想要的只是打印出一个列表 - 不要飞到月球上!)
如何做这样的事情?
也来自该系列:
您可以使用以下 bash 命令:
v4l2-ctl --list-devices
为了使用上述命令,您必须先安装软件包v4l-utils。在 Ubuntu/Debian 中你可以使用以下命令:
sudo apt-get install v4l-utils
只需按给定的类遍历 sysfs 设备即可轻松完成。以下命令行单行程序将执行此操作:
for I in /sys/class/video4linux/*; do cat $I/name; done
您可以在 C/C++ 应用程序中执行相同的操作,只需打开
/sys/class/video4linux
目录,它将具有指向所有网络摄像头作为 video4linux 设备的符号链接:
$ ls -al /sys/class/video4linux
drwxr-xr-x 2 root root 0 Ноя 27 12:19 ./
drwxr-xr-x 34 root root 0 Ноя 26 00:08 ../
lrwxrwxrwx 1 root root 0 Ноя 27 12:19 video0 -> ../../devices/pci0000:00/0000:00:13.2/usb2/2-5/2-5:1.0/video4linux/video0/
您可以按照每个符号链接到达每个设备的目录,并读取该目录中
name
文件的完整内容以获取名称。
这是我手头的代码片段。大概是从书上摘下来的。我想你可以迭代所有 /dev/videoN 节点并获取信息。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
int main(){
int fd;
struct video_capability video_cap;
struct video_window video_win;
struct video_picture video_pic;
if((fd = open("/dev/video0", O_RDONLY)) == -1){
perror("cam_info: Can't open device");
return 1;
}
if(ioctl(fd, VIDIOCGCAP, &video_cap) == -1)
perror("cam_info: Can't get capabilities");
else {
printf("Name:\t\t '%s'\n", video_cap.name);
printf("Minimum size:\t%d x %d\n", video_cap.minwidth, video_cap.minheight);
printf("Maximum size:\t%d x %d\n", video_cap.maxwidth, video_cap.maxheight);
}
if(ioctl(fd, VIDIOCGWIN, &video_win) == -1)
perror("cam_info: Can't get window information");
else
printf("Current size:\t%d x %d\n", video_win.width, video_win.height);
if(ioctl(fd, VIDIOCGPICT, &video_pic) == -1)
perror("cam_info: Can't get picture information");
else
printf("Current depth:\t%d\n", video_pic.depth);
close(fd);
return 0;
}
V4L2 文档表示每种类型可以有 64 个允许的设备。例如,对于路径 /dev/video,可以有 64 个设备,地址为 /dev/video0、/dev/video1、/dev/video2 ...
迭代 64 个设备,直到 ioctl 返回 ENIVAL(指定树的末尾)。
您还需要忽略元数据设备,例如
/dev/video1
(Ubuntu >= 19.10)
在该 Ubuntu 版本中,即使您只有一台相机,相关的 Linux 内核/模块现在也有一个
/dev/video1
设备,并且该设备包含 /dev/video0
的元数据。
如果您有第二个相机,那么
/dev/video2
将是相机,/dev/video3
是其元数据等等。
我们可以通过以下方式检查:
sudo v4l2-ctl --device=/dev/video0 --all
sudo v4l2-ctl --device=/dev/video1 --all
分别显示:
Device Caps : 0x04200001
Video Capture
Device Caps : 0x04a00000
Metadata Capture
TODO:了解如何从
/sys
查询该内容,以便更清晰地从 C/C++ 进行检测。也许“只使用偶数设备”规则也有效。
相关:
这里是使用 C/C++ 视频数据的演示:使用 GLSL 着色器进行图像处理?