open v4l2 device with index (#188)

This commit is contained in:
nihui
2025-04-21 21:25:44 +08:00
committed by GitHub
parent f6430431e0
commit 57b84b1011
3 changed files with 73 additions and 14 deletions

View File

@@ -61,7 +61,7 @@ public:
capture_v4l2_impl();
~capture_v4l2_impl();
int open(int width, int height, float fps);
int open(int index, int width, int height, float fps);
int start_streaming();
@@ -150,18 +150,18 @@ static float fit_score(int cap_width, int cap_height, int width, int height)
return iou * 20 + ioo * 80;
}
int capture_v4l2_impl::open(int width, int height, float fps)
int capture_v4l2_impl::open(int index, int width, int height, float fps)
{
int dev_index = -1;
// enumerate /dev/video%d and find capture + streaming
for (int i = 0; i < 64; i++)
// try index first
while (1)
{
sprintf(devpath, "/dev/video%d", i);
sprintf(devpath, "/dev/video%d", index);
fd = ::open(devpath, O_RDWR | O_NONBLOCK, 0);
if (fd < 0)
continue;
break;
// query cap
{
@@ -172,7 +172,7 @@ int capture_v4l2_impl::open(int width, int height, float fps)
{
fprintf(stderr, "%s ioctl VIDIOC_QUERYCAP failed %d %s\n", devpath, errno, strerror(errno));
::close(fd);
continue;
break;
}
fprintf(stderr, " devpath = %s\n", devpath);
@@ -195,21 +195,80 @@ int capture_v4l2_impl::open(int width, int height, float fps)
{
fprintf(stderr, "%s is not V4L2_CAP_VIDEO_CAPTURE or V4L2_CAP_VIDEO_CAPTURE_MPLANE\n", devpath);
::close(fd);
continue;
break;
}
if (!(caps.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr, "%s is not V4L2_CAP_STREAMING\n", devpath);
::close(fd);
continue;
break;
}
}
dev_index = i;
dev_index = index;
break;
}
if (dev_index == -1)
{
// enumerate /dev/video%d and find capture + streaming
for (int i = 0; i < 64; i++)
{
sprintf(devpath, "/dev/video%d", i);
fd = ::open(devpath, O_RDWR | O_NONBLOCK, 0);
if (fd < 0)
continue;
// query cap
{
struct v4l2_capability caps;
memset(&caps, 0, sizeof(caps));
if (ioctl(fd, VIDIOC_QUERYCAP, &caps))
{
fprintf(stderr, "%s ioctl VIDIOC_QUERYCAP failed %d %s\n", devpath, errno, strerror(errno));
::close(fd);
continue;
}
fprintf(stderr, " devpath = %s\n", devpath);
fprintf(stderr, " driver = %s\n", caps.driver);
fprintf(stderr, " card = %s\n", caps.card);
fprintf(stderr, " bus_info = %s\n", caps.bus_info);
fprintf(stderr, " version = %x\n", caps.version);
fprintf(stderr, " capabilities = %x\n", caps.capabilities);
fprintf(stderr, " device_caps = %x\n", caps.device_caps);
if (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)
{
buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
}
else if (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
{
buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
}
else
{
fprintf(stderr, "%s is not V4L2_CAP_VIDEO_CAPTURE or V4L2_CAP_VIDEO_CAPTURE_MPLANE\n", devpath);
::close(fd);
continue;
}
if (!(caps.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr, "%s is not V4L2_CAP_STREAMING\n", devpath);
::close(fd);
continue;
}
}
dev_index = i;
break;
}
}
if (dev_index == -1)
{
fprintf(stderr, "cannot find v4l device with VIDEO_CAPTURE and STREAMING\n");
@@ -916,9 +975,9 @@ capture_v4l2::~capture_v4l2()
delete d;
}
int capture_v4l2::open(int width, int height, float fps)
int capture_v4l2::open(int index, int width, int height, float fps)
{
return d->open(width, height, fps);
return d->open(index, width, height, fps);
}
int capture_v4l2::get_width() const

View File

@@ -30,7 +30,7 @@ public:
capture_v4l2();
~capture_v4l2();
int open(int width = 640, int height = 480, float fps = 30);
int open(int index, int width = 640, int height = 480, float fps = 30);
int get_width() const;
int get_height() const;

View File

@@ -158,7 +158,7 @@ bool VideoCapture::open(int index)
#if defined __linux__
if (capture_v4l2::supported())
{
int ret = d->cap_v4l2.open(d->width, d->height, d->fps);
int ret = d->cap_v4l2.open(index, d->width, d->height, d->fps);
if (ret == 0)
{
d->width = d->cap_v4l2.get_width();