4. 设置视频格式为YUYV
任务目标
通过 V4L2 接口将摄像头采集格式设置为 YUYV,分辨率设置为 640x480,并读取当前格式进行验证,确认设置生效。
核心实现
本案例使用 Linux 标准 V4L2 框架,通过 VIDIOC_S_FMT 设置格式,再用 VIDIOC_G_FMT 读回确认。代码不依赖第三方库,仅需内核头文件,适用于嵌入式 Linux 或桌面 Linux 环境。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
int main(int argc, char *argv[])
{
const char *dev = "/dev/video0";
int fd;
struct v4l2_format fmt;
if (argc > 1)
dev = argv[1];
fd = open(dev, O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
/* 1. 设置格式:YUYV 640x480 */
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("VIDIOC_S_FMT");
close(fd);
return 1;
}
/* 2. 读回实际生效的格式 */
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) {
perror("VIDIOC_G_FMT");
close(fd);
return 1;
}
/* 3. 打印并验证 */
printf("Driver: %s\n", dev);
printf("Width: %u\n", fmt.fmt.pix.width);
printf("Height: %u\n", fmt.fmt.pix.height);
printf("PixFmt: %c%c%c%c\n",
(fmt.fmt.pix.pixelformat >> 0) & 0xff,
(fmt.fmt.pix.pixelformat >> 8) & 0xff,
(fmt.fmt.pix.pixelformat >> 16) & 0xff,
(fmt.fmt.pix.pixelformat >> 24) & 0xff);
close(fd);
/* 4. 判定条件 */
if (fmt.fmt.pix.width == 640 &&
fmt.fmt.pix.height == 480 &&
fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
printf("RESULT: PASS\n");
return 0;
} else {
printf("RESULT: FAIL (driver adjusted parameters)\n");
return 1;
}
}
编译与运行
# 编译
gcc -o set_yuyv set_yuyv.c
# 运行(默认 /dev/video0,可指定其他设备)
./set_yuyv /dev/video0
验证方法
- 程序输出
Width: 640、Height: 480、PixFmt: YUYV,且最后一行显示RESULT: PASS,表示设置成功。 - 若输出
RESULT: FAIL,说明驱动不支持该格式或分辨率,实际参数已被驱动调整,可查看打印出的实际值确认驱动支持的能力。 - 也可用
v4l2-ctl --list-formats-ext -d /dev/video0预先确认设备是否支持 YUYV 640x480。
常见问题
- 打开设备失败:确认设备节点存在,且当前用户有读写权限(可尝试
sudo)。 - VIDIOC_S_FMT 返回错误:多为设备不支持 YUYV 或该分辨率,改用驱动支持的格式(如 MJPG)或降低分辨率测试。
- 设置后读回值不同:部分驱动会就近调整参数,以读回值为准,这是正常行为。