举例说明如何在linux下检测摄像头设备具备的功能
假设摄像头设备文件为/dev/video1
,下面是一个专门用于检测 /dev/video1
设备能力的简化程序。这个程序将打印出设备的所有能力、格式和其他相关信息,以帮助你了解设备支持的功能。
检测 /dev/video1
设备能力的程序
#include <fcntl.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <android/log.h>
#define LOG_TAG "DeviceCapabilityCheck"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
// 定义一个宏来检查特定的能力是否被设置
#define CHECK_CAPABILITY(capability) \
if (cap.capabilities & capability) { \
LOGD(" - " #capability); \
}
int xioctl(int fh, int request, void *arg) {
int r;
do {
r = ioctl(fh, request, arg);
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
if (r == -1) {
perror("ioctl failed");
exit(EXIT_FAILURE);
}
return r;
}
void print_supported_pixel_formats(int fd) {
struct v4l2_fmtdesc fmtdesc;
memset(&fmtdesc, 0, sizeof(fmtdesc));
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; // 使用多平面类型
LOGD("Supported pixel formats:");
int index = 0;
while (true) {
fmtdesc.index = index++;
if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == -1) {
if (errno == EINVAL) break; // 没有更多的格式了
perror("VIDIOC_ENUM_FMT failed");
return;
}
LOGD(" - %s (0x%08x)", fmtdesc.description, fmtdesc.pixelformat);
}
}
int main() {
const char *dev_name = "/dev/video1";
LOGD("Checking capabilities for device %s", dev_name);
int fd = open(dev_name, O_RDWR);
if (fd == -1) {
perror("Cannot open device");
return EXIT_FAILURE;
}
// 查询设备能力
struct v4l2_capability cap;
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
perror("Querying capabilities failed");
close(fd);
return EXIT_FAILURE;
}
LOGD("Device capabilities: 0x%08x", cap.capabilities);
LOGD("Device bus info: %s", cap.bus_info);
LOGD("Device driver: %s", cap.driver);
LOGD("Device card: %s", cap.card);
LOGD("Device capabilities detailed:");
CHECK_CAPABILITY(V4L2_CAP_VIDEO_CAPTURE);
CHECK_CAPABILITY(V4L2_CAP_VIDEO_CAPTURE_MPLANE); // 添加对多平面的支持检查
CHECK_CAPABILITY(V4L2_CAP_VIDEO_OUTPUT);
CHECK_CAPABILITY(V4L2_CAP_VIDEO_OVERLAY);
CHECK_CAPABILITY(V4L2_CAP_VBI_CAPTURE);
CHECK_CAPABILITY(V4L2_CAP_VBI_OUTPUT);
CHECK_CAPABILITY(V4L2_CAP_SLICED_VBI_CAPTURE);
CHECK_CAPABILITY(V4L2_CAP_SLICED_VBI_OUTPUT);
CHECK_CAPABILITY(V4L2_CAP_RDS_CAPTURE);
CHECK_CAPABILITY(V4L2_CAP_VIDEO_OUTPUT_OVERLAY);
CHECK_CAPABILITY(V4L2_CAP_HW_FREQ_SEEK);
CHECK_CAPABILITY(V4L2_CAP_RDS_OUTPUT);
CHECK_CAPABILITY(V4L2_CAP_READWRITE);
CHECK_CAPABILITY(V4L2_CAP_ASYNCIO);
CHECK_CAPABILITY(V4L2_CAP_STREAMING);
// 打印支持的像素格式
print_supported_pixel_formats(fd);
close(fd);
return 0;
}
关键更改点
-
多平面类型:
- 在
print_supported_pixel_formats
函数中,我们将fmtdesc.type
设置为V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
以匹配设备的能力。
- 在
-
错误处理:
- 在枚举格式时添加了更详细的错误处理,以便在遇到无效索引时停止枚举。
-
能力检查:
- 添加了对
V4L2_CAP_VIDEO_CAPTURE_MPLANE
的检查,以确认设备支持多平面视频捕获。
- 添加了对