使用如下代码设定摄像头的分辨率:
#define CAMERA_RESOLUTION_WIDTH ( 1280u)
#define CAMERA_RESOLUTION_HEIGHT ( 720u)
/**********************************************
* other codes
* ********************************************/
/*******************************************************************************
- Function : __SetCameraResolution
- Description : 本函数设置摄像头输出格式。
- Input : void
- Output : null
- Return : void
- Others :
*******************************************************************************/
void __SetCameraResolution(void)
{
struct v4l2_format stFormat ;
memset(&stFormat, 0, sizeof(stFormat)) ;
/* 设置输出格式 */
stFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
stFormat.fmt.pix.width = CAMERA_RESOLUTION_WIDTH ;
stFormat.fmt.pix.height = CAMERA_RESOLUTION_HEIGHT ;
stFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV ; /* 根据需要的格式填写 */
if(-1 == ioctl(g_iFDVideo, VIDIOC_S_FMT, &stFormat))
{
printf("ioctl VIDIOC_S_FMT error.\n") ;
exit(-1) ;
}
/* 检查设置效果 */
stFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
if(-1 == ioctl(g_iFDVideo, VIDIOC_G_FMT, &stFormat))
{
printf("ioctl VIDIOC_G_FMT error.\n") ;
exit(-1) ;
}
else
{
printf("--Set format result---------------------------------------\n") ;
printf("-- Resolution width : %d\n"
"-- Resolution height : %d\n"
"-- Pixel format : %c%c%c%c\n",
stFormat.fmt.pix.width, stFormat.fmt.pix.height,
stFormat.fmt.pix.pixelformat & 0xFF,
(stFormat.fmt.pix.pixelformat >> 8) & 0xFF,
(stFormat.fmt.pix.pixelformat >> 16) & 0xFF,
(stFormat.fmt.pix.pixelformat >> 24) & 0xFF);
printf("----------------------------------------------------------\n\n\n") ;
}
return ;
}
使用如下代码设定摄像头的输出帧率:
#define CAMERA_FPS ( 30u)
/**********************************************
* other codes
* ********************************************/
/*******************************************************************************
- Function : __SetCameraFPS
- Description : 本函数设置摄像头输出格式。
- Input : void
- Output : null
- Return : void
- Others :
*******************************************************************************/
void __SetCameraFPS(void)
{
struct v4l2_streamparm stStreamParm ;
stStreamParm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
/* 获取当前设置 */
if(-1 == ioctl(g_iFDVideo, VIDIOC_G_PARM, &stStreamParm))
{
printf("ioctl VIDIOC_G_PARM error.\n") ;
exit(-1) ;
}
else
{
printf("--Previous camera stream param----------------------------\n") ;
printf("-- Capability : %08x\n"
"-- Capturemode : %08x\n"
"-- Numerator : %d\n"
"-- Denominator : %d\n",
stStreamParm.parm.capture.capability,
stStreamParm.parm.capture.capturemode,
stStreamParm.parm.capture.timeperframe.numerator,
stStreamParm.parm.capture.timeperframe.denominator) ;
printf("----------------------------------------------------------\n\n\n") ;
}
/* 修改FPS */
stStreamParm.parm.capture.timeperframe.numerator = 1 ;
stStreamParm.parm.capture.timeperframe.denominator = CAMERA_FPS ;
if(-1 == ioctl(g_iFDVideo, VIDIOC_S_PARM, &stStreamParm))
{
printf("ioctl VIDIOC_S_PARM error.\n") ;
exit(-1) ;
}
/* 获取新设置 */
if(-1 == ioctl(g_iFDVideo, VIDIOC_G_PARM, &stStreamParm))
{
printf("ioctl VIDIOC_G_PARM error.\n") ;
exit(-1) ;
}
else
{
printf("--Current camera stream param-----------------------------\n") ;
printf("-- Capability : %08x\n"
"-- Capturemode : %08x\n"
"-- Numerator : %d\n"
"-- Denominator : %d\n",
stStreamParm.parm.capture.capability,
stStreamParm.parm.capture.capturemode,
stStreamParm.parm.capture.timeperframe.numerator,
stStreamParm.parm.capture.timeperframe.denominator) ;
printf("----------------------------------------------------------\n\n\n") ;
}
return ;
}
使用命令 VIDIOC_S_FMT 来设定输出格式。命令原型为:
#define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format)
可见,需要一个 v4l2_format 结构体。结构体的定义如下:
/**
* struct v4l2_format - stream data format
* @type: enum v4l2_buf_type; type of the data stream
* @pix: definition of an image format
* @pix_mp: definition of a multiplanar image format
* @win: definition of an overlaid image
* @vbi: raw VBI capture or output parameters
* @sliced: sliced VBI capture or output parameters
* @raw_data: placeholder for future extensions and custom formats
* @fmt: union of @pix, @pix_mp, @win, @vbi, @sliced, @sdr, @meta
* and @raw_data
*/
struct v4l2_format {
__u32 type;
union {
struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
struct v4l2_pix_format_mplane pix_mp; /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
struct v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
struct v4l2_sdr_format sdr; /* V4L2_BUF_TYPE_SDR_CAPTURE */
struct v4l2_meta_format meta; /* V4L2_BUF_TYPE_META_CAPTURE */
__u8 raw_data[200]; /* user-defined */
} fmt;
};
结构体中:
type 应指定为:V4L2_BUF_TYPE_VIDEO_CAPTURE;
联合体中,使用 v4l2_pix_format。该结构体的定义如下:
struct v4l2_pix_format {
__u32 width;
__u32 height;
__u32 pixelformat;
__u32 field; /* enum v4l2_field */
__u32 bytesperline; /* for padding, zero if unused */
__u32 sizeimage;
__u32 colorspace; /* enum v4l2_colorspace */
__u32 priv; /* private data, depends on pixelformat */
__u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */
union {
/* enum v4l2_ycbcr_encoding */
__u32 ycbcr_enc;
/* enum v4l2_hsv_encoding */
__u32 hsv_enc;
};
__u32 quantization; /* enum v4l2_quantization */
__u32 xfer_func; /* enum v4l2_xfer_func */
};
这里主要填写 width、height、pixelformat三个成员。
width 指输出图像的宽度;
height指输出图像的高度;
pixelformat指输出图像的像素格式。根据需要填写 V4L2_PIX_FMT_XXXX。
设置执行后,未必能执行成功。需要读出再检查。读出设置,使用 VIDIOC_G_FMT 命令。该命令的原型为:
#define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format)
返回值同样为 struct v4l2_format 类型。
使用命令 VIDIOC_G_PARM 来获取当前摄像头的参数(包含帧率)。该命令的原型是:
#define VIDIOC_G_PARM _IOWR('V', 21, struct v4l2_streamparm)
该命令需要一个 struct v4l2_streamparm 类型的参数。
struct v4l2_streamparm {
__u32 type; /* enum v4l2_buf_type */
union {
struct v4l2_captureparm capture;
struct v4l2_outputparm output;
__u8 raw_data[200]; /* user-defined */
} parm;
};
对于摄像头,type 仍然填写 V4L2_BUF_TYPE_VIDEO_CAPTURE。
联合体中,对于摄像头而言,应该取 struct v4l2_captureparm capture。该结构体的定义如下:
struct v4l2_captureparm {
__u32 capability; /* Supported modes */
__u32 capturemode; /* Current mode */
struct v4l2_fract timeperframe; /* Time per frame in seconds */
__u32 extendedmode; /* Driver-specific extensions */
__u32 readbuffers; /* # of buffers for read */
__u32 reserved[4];
};
和帧率有关的是其中的结构体成员 struct v4l2_fract timeperframe 。其定义如下:
struct v4l2_fract {
__u32 numerator;
__u32 denominator;
};
参数 timeperframe ,意指每一帧图像的输出时间。成员 numerator (分子)和 denominator (分母)参数决定了具体的值。例如:
numerator = 1
denominator = 30
则表明每一帧的时间为1/30秒,则相当于30fps输出。此外:
numerator = 100
denominator = 3000
效果是一样的。
需要注意的是,摄像头未必能按照设定的参数来输出。主要有2点:
使用命令 VIDIOC_S_PARM 来设置设定的参数。命令的定义:
#define VIDIOC_S_PARM _IOWR('V', 22, struct v4l2_streamparm)
同样还是需要结构体 struct v4l2_streamparm。
同设定输出格式一样,也需要检查是否设定成功。
材料:
--Set format result---------------------------------------
-- Resolution width : 1280
-- Resolution height : 720
-- Pixel format : YUYV
----------------------------------------------------------
--Previous camera stream param----------------------------
-- Capability : 00001000
-- Capturemode : 00000000
-- Numerator : 1000
-- Denominator : 30000
----------------------------------------------------------
--Current camera stream param-----------------------------
-- Capability : 00001000
-- Capturemode : 00000000
-- Numerator : 1
-- Denominator : 30
----------------------------------------------------------
可以看到,在设置帧率之前, Numerator 参数和 Denominator参数,分别是1000和30000,即帧率是30fps。设置后仍然是30fps。
上述代码中,如果修改帧率设置:
numerator = 1
denominator = 100
则打印信息为:
--Current camera stream param-----------------------------
-- Capability : 00001000
-- Capturemode : 00000000
-- Numerator : 1
-- Denominator : 90
----------------------------------------------------------
可见,Denominator 参数被修改为了90,相当于最大输出90fps。此时尝试连续捕获,最终计算帧率为:
FPS : 90.25