树莓派学习专题<8>:使用V4L2驱动获取摄像头数据--获取摄像头支持的分辨率
- [1. 获取摄像头支持的分辨率](#1. 获取摄像头支持的分辨率)
- [2. 代码分析](#2. 代码分析)
- [3. 树莓派实测](#3. 树莓派实测)
1. 获取摄像头支持的分辨率
使用如下代码获取摄像头支持的输出分辨率。
c
struct v4l2_frmsizeenum stFrameSize ;
/**********************************************
* other codes
* ********************************************/
stFrameSize.index = 0 ;
stFrameSize.pixel_format = V4L2_PIX_FMT_YUYV ;
printf("--Frame resolution descriptor ----------------------------\n") ;
while(-1 != ioctl(g_iFDVideo, VIDIOC_ENUM_FRAMESIZES, &stFrameSize))
{
printf("-- %d. %c%c%c%c ",
stFrameSize.index + 1,
(stFrameSize.pixel_format >> 0) & 0xff,
(stFrameSize.pixel_format >> 8) & 0xff,
(stFrameSize.pixel_format >> 16) & 0xff,
(stFrameSize.pixel_format >> 24) & 0xff) ;
if(V4L2_FRMSIZE_TYPE_DISCRETE == stFrameSize.type)
{
printf("type : DISCRETE\n\t\t width : %d\n\t\t height : %d\n",
stFrameSize.discrete.width,
stFrameSize.discrete.height) ;
}
else if(V4L2_FRMSIZE_TYPE_CONTINUOUS == stFrameSize.type)
{
printf("type : CONTINUOUS\n") ;
}
else if(V4L2_FRMSIZE_TYPE_STEPWISE == stFrameSize.type)
{
printf("type : STEPWISE\n"
"\t\t min_width : %d\n"
"\t\t max_width : %d\n"
"\t\t step_width : %d\n"
"\t\t min_height : %d\n"
"\t\t max_height : %d\n"
"\t\t step_height : %d\n",
stFrameSize.stepwise.min_width,
stFrameSize.stepwise.max_width,
stFrameSize.stepwise.step_width,
stFrameSize.stepwise.min_height,
stFrameSize.stepwise.max_height,
stFrameSize.stepwise.step_height) ;
}
stFrameSize.index++ ;
}
printf("----------------------------------------------------------\n\n\n") ;
2. 代码分析
使用 VIDIOC_ENUM_FRAMESIZES 命令来获取摄像头支持的分辨率。该命令需要一个 struct v4l2_frmsizeenum 类型的参数。
该结构体的定义:
c
struct v4l2_frmsizeenum {
__u32 index; /* Frame size number */
__u32 pixel_format; /* Pixel format */
__u32 type; /* Frame size type the device supports. */
union { /* Frame size */
struct v4l2_frmsize_discrete discrete;
struct v4l2_frmsize_stepwise stepwise;
};
__u32 reserved[2]; /* Reserved space for future use */
};
- index 为序号,从0开始指定。
- pixel_format 像素格式。根据前述的 VIDIOC_ENUM_FMT 命令获取到的摄像头支持的格式填写。例如 **V4L2_PIX_FMT_YUYV ** 。
- type 为摄像头像素支持的分辨率类型。其可能有3个取值:
c
enum v4l2_frmsizetypes {
V4L2_FRMSIZE_TYPE_DISCRETE = 1,
V4L2_FRMSIZE_TYPE_CONTINUOUS = 2,
V4L2_FRMSIZE_TYPE_STEPWISE = 3,
};
如果是类型 V4L2_FRMSIZE_TYPE_DISCRETE ,则结构体 v4l2_frmsizeenum 中,联合体取 discrete 。说明该摄像头支持特定值的分辨率(特定的宽、高)。
如果是类型 V4L2_FRMSIZE_TYPE_STEPWISE ,则结构体 v4l2_frmsizeenum 中,联合体取 stepwise 。说明该摄像头支持一系列步进的分辨率。
大多数CIS(CMOS image sensor)都支持 stepwise ,即分辨率是可调的。因此如果接口是MIPI-CSI,估计大多数都是 stepwise 类型。如果是USB摄像头,摄像头内部带有主控,限制了分辨率,因此可能是 discrete 。此点纯属猜测。
- struct v4l2_frmsize_discrete 类型如下。此时摄像头支持特定宽高的分辨率。
c
struct v4l2_frmsize_discrete {
__u32 width; /* Frame width [pixel] */
__u32 height; /* Frame height [pixel] */
};
- struct v4l2_frmsize_stepwise 类型如下。此时摄像头支持一定步进的分辨率。
c
struct v4l2_frmsize_stepwise {
__u32 min_width; /* Minimum frame width [pixel] */
__u32 max_width; /* Maximum frame width [pixel] */
__u32 step_width; /* Frame width step size [pixel] */
__u32 min_height; /* Minimum frame height [pixel] */
__u32 max_height; /* Maximum frame height [pixel] */
__u32 step_height; /* Frame height step size [pixel] */
};
其中,:
min_width 为最小宽度,max_width 为最大宽度,step_width 为宽度步进值。
min_height 为最小高度,max_height 为最大高度,step_height 为高度步进值。
3. 树莓派实测
材料:
- Raspberry Pi 4B计算机;
- IMX219摄像头组件。
运行上述代码,打印结果:
c
--Frame resolution descriptor ----------------------------
-- 1. YUYV type : STEPWISE
min_width : 32
max_width : 3280
step_width : 2
min_height : 32
max_height : 2464
step_height : 2
----------------------------------------------------------
可见,树莓派IMX219 摄像头,当输出格式指定为YUYV 时,输出宽度可在32 到3280 之间,以2 为步进调节;输出高度可在32 至2464 之间,以2为步进调节。
需要注意的是,指定不同的pixel_format 时,可能获取到不同的分辨率支持。