如何获取 Linux ( ubuntu ) 上的视频捕获设备(网络摄像头)列表? (C/C++)

发布于 2024-10-05 10:02:41 字数 1138 浏览 4 评论 0原文

所以我需要的很简单 - 当前可用的视频捕获设备(网络摄像机)的列表。我需要它在简单的 C 或 C++ 控制台应用程序中。我所说的列表是指类似控制台输出的内容:

1) Asus Web Camera
2) Sony Web Camera

看起来很简单,但我有一个要求 - 尽可能多地使用本机操作系统 api - 没有外部库 - 毕竟 - 我们想要的只是打印出一个列表 - 不是飞行到月球上!)

如何做这样的事情?


也来自本系列:

So all I need is simple - a list of currently avaliable video capture devices (web cameras). I need it in simple C or C++ console app. By list I mean something like such console output:

1) Asus Web Camera
2) Sony Web Camera

So It seems simple but I have one requirement - use of native OS apis as much as possible - no external libs - after all - all we want is to print out a a list - not to fly onto the moon!)

How to do such thing?


also from this series:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

黯然#的苍凉 2024-10-12 10:02:41

您可以使用以下bash命令:

v4l2-ctl --list-devices

为了使用上述命令,您必须先安装软件包v4l-utils。在 Ubuntu/Debian 中你可以使用以下命令:

sudo apt-get install v4l-utils

You can use the following bash command:

v4l2-ctl --list-devices

In order to use the above command, you must install package v4l-utils before. In Ubuntu/Debian you can use the command:

sudo apt-get install v4l-utils
执着的年纪 2024-10-12 10:02:41

只需按给定的类遍历 sysfs 设备即可轻松完成。下面的命令行一行将执行此操作:

for I in /sys/class/video4linux/*; do cat $I/name; done

您可以在 C/C++ 应用程序中执行相同的操作,只需打开 /sys/class/video4linux 目录,它将具有指向所有 Web 的符号链接相机作为 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 文件的完整内容以获取名称。

It's easy by just traversing sysfs devices by a given class. The following command-line one liner would do so:

for I in /sys/class/video4linux/*; do cat $I/name; done

You can do the same thing in C/C++ application, by just opening up /sys/class/video4linux directory, it will have symlinks to all your web cameras as video4linux devices:

$ 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/

You can follow every symlink to a directory of every device and read full contents of name file in that directory to get the name.

冧九 2024-10-12 10:02:41

这是我闲置的一段代码片段。大概是从书上摘下来的。我想您可以迭代所有 /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;
}

This is a code snippet I had laying around. Probably from a book. I guess you could just iterate over all /dev/videoN nodes and get the info.

#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;
}
如梦初醒的夏天 2024-10-12 10:02:41

V4L2 文档表示每种类型可以有 64 个允许的设备。例如,对于路径 /dev/video,可以有 64 个设备,地址为 /dev/video0、/dev/video1、/dev/video2 ...

迭代 64 个设备,直到 ioctl 返回指定树末尾的 ENIVAL。

V4L2 documentation says that there can be 64 allowed devices for each type. For instance for path /dev/video there can be 64 devices addresssed as /dev/video0, /dev/video1, /dev/video2 ...

Iterate over 64 devices until the ioctl retuens ENIVAL which specifies end of the tree.

樱&纷飞 2024-10-12 10:02:41

您还需要忽略元数据设备,例如 /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++ 视频数据的演示: < a href="https://stackoverflow.com/questions/13693946/image-processing-with-glsl-shaders/40641014#40641014">使用 GLSL 着色器进行图像处理?

You also need to ignore metadata devices like /dev/video1 (Ubuntu >= 19.10)

At that Ubuntu version, the relevant Linux kernel/modules now have a /dev/video1 device even if you have just one camera, and this device contains metadata for /dev/video0.

If you have a second camera, then /dev/video2 would be the camera, and /dev/video3 its metadata and so on.

We can check this with:

sudo v4l2-ctl --device=/dev/video0 --all
sudo v4l2-ctl --device=/dev/video1 --all

which shows respectively:

        Device Caps      : 0x04200001
                Video Capture 

        Device Caps      : 0x04a00000
                Metadata Capture

TODO: find out how to query that from /sys to make it cleaner to detect from C/C++. Perhaps the "only use even devices" rule also works.

Related:

Here's a demo of using the video data from C/C++: Image Processing with GLSL shaders?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文