Linux中接入摄像头后会在/dev/video*
中有多个描述文件,所以获取摄像头的VID
及PID
值还是较为有用的
首先找到可以捕获视频的设备
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64#include <dirent.h>
#include <libudev.h>
#include <fstream>
#include <pthread.h>
#include <time.h>
#include <vector>
#include <unistd.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>//v4l2相关结构体
#include <string.h>
int v4l2_is_v4l_dev(const char *name)
{
return !strncmp(name, "video", 5) || !strncmp(name, "radio", 5) || !strncmp(name, "vbi", 3) || !strncmp(name, "v4l-subdev", 10);
}
int main(){
const char* dir_name = "/dev";
DIR* dir = opendir(dir_name);
if (!dir) {
fprintf(stderr, "Error: couldn't open the directory: %s\n", dir_name);
return false;
}
struct dirent* entry = nullptr;
int fd;
while ((entry = readdir(dir))) {
if (!v4l2_is_v4l_dev(entry->d_name))
continue;
char device_name[256];
snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name);
if ((fd = open(device_name, O_RDWR | O_NONBLOCK)) < 0) {
continue;
}
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
fprintf(stderr, "Error: cam_info: can't open device: %s\n", device_name);
close(fd);
break;
} else {
if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || !(cap.capabilities & V4L2_CAP_STREAMING) || !(cap.capabilities & V4L2_CAP_META_CAPTURE)) {
close(fd);
continue;
} else {
printf("enable: %s\n", device_name);
close(fd);
}
}
}
return 0;
}获取
vid
及pid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52#define udev_list_entry_foreach(entry, first) \
for (entry = first; \
entry != NULL; \
entry = udev_list_entry_get_next(entry))
typedef struct {
string vid;
string pid;
} VPID;
bool read_vpid(string dev_path, VPID& vpid)
{
bool success = false;
auto udev = udev_new();
if (!udev) {
return false;
}
struct stat statbuf;
if (stat(dev_path.c_str(), &statbuf) < 0) {
return false;
}
auto type = S_ISBLK(statbuf.st_mode) ? 'b' : S_ISCHR(statbuf.st_mode) ? 'c' : 0;
auto opened_dev = udev_device_new_from_devnum(udev, type, statbuf.st_rdev);
auto dev = opened_dev;
struct udev_list_entry *list_entry;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(dev))
{
success = true;
if(strcmp(udev_list_entry_get_name(list_entry), "ID_VENDOR_ID") == 0)
vpid.vid = udev_device_get_property_value(dev, udev_list_entry_get_name(list_entry));
if(strcmp(udev_list_entry_get_name(list_entry), "ID_MODEL_ID") == 0)
vpid.pid = udev_device_get_property_value(dev, udev_list_entry_get_name(list_entry));
//printf("==== vid: %s\n pid: %s\n", vpid.vid.c_str(), vpid.pid.c_str());
//printf("%s=%s\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry));
}
printf("\n");
if (opened_dev) {
udev_device_unref(opened_dev);
}
udev_unref(udev);
return success;
}
# 根据vid、pid可区分具体的摄像头