从应用调用vivi驱动分析v4l2 -- 设置图像格式(VIDIOC_S_FMT)

Linux v4l2架构学习总链接

vivi代码

v4l2测试代码

step 4 : 设置图像格式

1.枚举支持的像素格式

struct v4l2_fmtdesc fmtdesc;

fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmtdesc.index = 0;

while (!ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc))
{
    //....
}

对应vivi驱动的vidioc_enum_fmt_vid_cap

static struct vivi_fmt formats[] = {
	{
		.name     = "4:2:2, packed, YUYV",
		.fourcc   = V4L2_PIX_FMT_YUYV,
		.depth    = 16,
	},
	{
		.name     = "4:2:2, packed, UYVY",
		.fourcc   = V4L2_PIX_FMT_UYVY,
		.depth    = 16,
	},
	{
		.name     = "RGB565 (LE)",
		.fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
		.depth    = 16,
	},
	{
		.name     = "RGB565 (BE)",
		.fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
		.depth    = 16,
	},
	{
		.name     = "RGB555 (LE)",
		.fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
		.depth    = 16,
	},
	{
		.name     = "RGB555 (BE)",
		.fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
		.depth    = 16,
	},
};


static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
					struct v4l2_fmtdesc *f)
{
	struct vivi_fmt *fmt;

	if (f->index >= ARRAY_SIZE(formats))
		return -EINVAL;

	fmt = &formats[f->index];

	strlcpy(f->description, fmt->name, sizeof(f->description));
	f->pixelformat = fmt->fourcc;
	return 0;
}

可以看到将name和forcc返回给用户空间了,应用代码测试如下

        fmtdesc.index = 0;
        fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        while (!ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) {
                printf("fmt name: [%s]\n", fmtdesc.description);
                printf("fmt pixelformat : '%c%c%c%c', description = '%s'\n",fmtdesc.pixelformat & 0xFF,
                                (fmtdesc.pixelformat >> 8) & 0xFF,(fmtdesc.pixelformat >> 16) & 0xFF,
                                (fmtdesc.pixelformat >> 24) & 0xFF,fmtdesc.description);
                fmtdesc.index++;
        }

打印如下

fmt name: [YUYV 4:2:2]
fmt pixelformat : 'YUYV', description = 'YUYV 4:2:2'
fmt name: [UYVY 4:2:2]
fmt pixelformat : 'UYVY', description = 'UYVY 4:2:2'
fmt name: [16-bit RGB 5-6-5]
fmt pixelformat : 'RGBP', description = '16-bit RGB 5-6-5'
fmt name: [16-bit RGB 5-6-5 BE]
fmt pixelformat : 'RGBR', description = '16-bit RGB 5-6-5 BE'
fmt name: [16-bit A/XRGB 1-5-5-5]
fmt pixelformat : 'RGBO', description = '16-bit A/XRGB 1-5-5-5'
fmt name: [16-bit A/XRGB 1-5-5-5 BE]
fmt pixelformat : 'RGBQ', description = '16-bit A/XRGB 1-5-5-5 BE'

可以看到列举出来支持的格式,这里我们选择格式 YUYV 4:2:2

2,设置图像格式

memset(&v4l2_fmt, 0, sizeof(struct v4l2_format));
v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
v4l2_fmt.fmt.pix.width = width; //宽度
v4l2_fmt.fmt.pix.height = height; //高度
v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //像素格式
v4l2_fmt.fmt.pix.field = V4L2_FIELD_ANY;

if (ioctl(fd, VIDIOC_S_FMT, &v4l2_fmt) < 0)

这里对应vivi驱动的vidioc_s_fmt_vid_cap

static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
					struct v4l2_format *f)
{
	struct vivi_dev *dev = video_drvdata(file);
	struct vb2_queue *q = &dev->vb_vidq;

	int ret = vidioc_try_fmt_vid_cap(file, priv, f);
	if (ret < 0)
		return ret;

        /*
         * vb2_is_streaming 判断vb2_is_streaming的值,后面的分析我们会看到这个值
         * 的变化,这里认为值为0,if不满足
         */


	if (vb2_is_streaming(q)) {
		dprintk(dev, 1, "%s device busy\n", __func__);
		return -EBUSY;
	}

	dev->fmt = get_format(f);
	dev->width = f->fmt.pix.width;
	dev->height = f->fmt.pix.height;
	dev->field = f->fmt.pix.field;

	return 0;
}

这里可以看到,vivi驱动中还有一个检查,另外将数据放到了dev相关成员中。

完整应用操作如下

        memset(&fmt, 0, sizeof(struct v4l2_format));
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.width = 1920;
        fmt.fmt.pix.height = 1080;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        fmt.fmt.pix.field = V4L2_FIELD_ANY;

        if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
                printf("Set format fail\n");
                goto err;
        }

对于这里的field,可以去看这篇博客,写的很好。https://blog.csdn.net/kickxxx/article/details/6367669

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dianlong_lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值