#include <sys/ioctl.h> /* ioctl() */
#include <fcntl.h> /* open() */
#include <linux/videodev2.h> /* V4L2 相关结构体与 ioctl 宏 */
#include <unistd.h> /* close() */
#include <stdio.h> /* printf() */
#include <stdlib.h> /* EXIT_FAILURE 等 */
#include <string.h> /* memset() */
/* 默认摄像头设备节点,可通过修改此变量更换设备 */
static char *dev = "/dev/video0";
static void enum_framesizes(int fd, unsigned int pixelformat)
{
struct v4l2_frmsizeenum frmsize;
for (int i = 0; ; i++) {
memset(&frmsize, 0, sizeof(frmsize));
frmsize.pixel_format = pixelformat;
frmsize.index = i;
/* VIDIOC_ENUM_FRAMESIZES 根据 pixel_format + index 查询分辨率 */
if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) < 0)
break;
switch (frmsize.type) {
case V4L2_FRMSIZE_TYPE_DISCRETE:
/* 离散分辨率:每次返回一个具体的宽高值 */
printf(" [%d] %dx%d\n", i,
frmsize.discrete.width,
frmsize.discrete.height);
break;
case V4L2_FRMSIZE_TYPE_STEPWISE:
/*
* 步进范围:min~max 范围内按 step 递增。
* 例如 min_width=320, max_width=1920, step_width=160 表示
* 支持 320, 480, 640, ..., 1920 这些宽度值。
* 一次调用即得全部信息,return 退出函数,不再继续循环。
*/
printf(" stepwise: %dx%d ~ %dx%d step %dx%d\n",
frmsize.stepwise.min_width, frmsize.stepwise.min_height,
frmsize.stepwise.max_width, frmsize.stepwise.max_height,
frmsize.stepwise.step_width, frmsize.stepwise.step_height);
return;
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
/*
* 连续范围:min~max 之间任意分辨率都支持。
* 实际上驱动通常会限制一定的粒度,这里只是"名义上连续"。
* 一次调用即得全部信息,return 退出函数。
*/
printf(" continuous: %dx%d ~ %dx%d\n",
frmsize.stepwise.min_width, frmsize.stepwise.min_height,
frmsize.stepwise.max_width, frmsize.stepwise.max_height);
return;
}
}
}
static void enum_format_with_sizes(int fd)
{
struct v4l2_fmtdesc fmt;
printf("====== 枚举像素格式及支持的分辨率 ======\n");
/* memset 清零:避免结构体中的残留数据影响 ioctl 行为 */
memset(&fmt, 0, sizeof(fmt));
/* 设置缓冲区类型为视频捕获,其他类型还有 V4L2_BUF_TYPE_VIDEO_OUTPUT 等 */
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (fmt.index = 0; ; fmt.index++) {
if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) < 0)
break;
/* fmt.pixelformat 是 FourCC 码(如 0x56595559 即 "YUYV") */
printf(" [%d] 0x%08x %s\n",
fmt.index,
fmt.pixelformat,
fmt.description);
/* 对每种格式查询其支持的分辨率 */
enum_framesizes(fd, fmt.pixelformat);
}
printf("\n");
}
int main(void)
{
int fd;
/*
* 打开 V4L2 设备节点。
* O_RDWR:读写模式,既可用于查询(G_FMT/ENUM_FMT)也可用于设置(S_FMT)。
* 部分设备可能只需要 O_RDONLY,但 O_RDWR 兼容性最好。
*/
fd = open(dev, O_RDWR);
if (fd < 0) {
perror("open"); /* perror 会打印 "open: <系统错误信息>" */
return -1;
}
/* 枚举所有像素格式及其支持的分辨率 */
enum_format_with_sizes(fd);
close(fd);
return 0;
}
root@wyl:~/c-std/for-linux/099_other/v4l2# ./002_v4l2_fmt_pix
====== 枚举像素格式及支持的分辨率 ======
[0] 0x56595559 YUYV 4:2:2
分辨率:
[0] 96x200
[1] 200x96
[2] 8x8448
[3] 8448x8
[4] 4x2321
[5] 96x100
[6] 4x2637
[7] 4x14733
[8] 4x5188
[9] 5188x4
[10] 8x8642
[11] 8642x8
[12] 96x96
[13] 240x240