#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