我是靠谱客的博主 过时洋葱,最近开发中收集的这篇文章主要介绍记一次 VIDIOC_REQBUFS failed 问题Linux v4l2架构学习总链接,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Linux v4l2架构学习总链接

最近更新了一个手里板子的sdk,在写应用测试vivi驱动的时候,出现了一个错误。

	req.count = 5;
	req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	req.memory = V4L2_MEMORY_MMAP;
	if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
		printf("Reqbufs failn");
		goto err;
	}
Reqbufs fail

这里比较奇怪,于是打算去分析一下原因。

static int vidioc_reqbufs(struct file *file, void *priv,
			  struct v4l2_requestbuffers *p)
{
	struct vivi_dev *dev = video_drvdata(file);
	return vb2_reqbufs(&dev->vb_vidq, p);
}

从vivi的reqbufs开始分析,发现会使用vb2_reqbufs

这个函数的代码位置是 kernel/drivers/media/common/videobuf2/videobuf2-v4l2.c

打开其对应的打印信息

echo 7 > /sys/module/videobuf2_common/parameters/debug

执行应用程序

打印信息如下

videobuf2_common: vb2_verify_memory_type: file io in progress

对应的代码位置 vb2_verify_memory_type

判断q->fileio的值非空,则就会打印这个信息。

由于不想去改内核代码,所以决定修改vivi驱动,加一些打印信息

static int vidioc_reqbufs(struct file *file, void *priv,
                          struct v4l2_requestbuffers *p)
{
        struct vivi_dev *dev = video_drvdata(file);
        struct vb2_queue *q = &dev->vb_vidq;


        printk(KERN_ERR "%sn", __func__);

        if (vb2_fileio_is_active(q))
                printk(KERN_ERR "q->fileio --------------n");
        return vb2_reqbufs(&dev->vb_vidq, p);
}

但是测试的时候,q->fileio -----这条语句并没有打印,没办法打算内核中加打印

int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
{
        int ret;
        printk(KERN_ERR "%sn", __func__);
        ret = vb2_verify_memory_type(q, req->memory, req->type);
        printk(KERN_ERR "%s 1111n", __func__);
        return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
}

并且在vb2_core_reqbufs中也加了打印信息

测试发现vb2_core_reqbufs中打印信息没有出现,所以可以定位到就是这里的vb2_verify_memory_type出了问题

由于是更新了sdk

怀疑是不是打开摄像头的这些步骤中加了一些其他的东西,追了一下并没有发现什么改动。

但是同样结构体经过一个函数后,成员值变了,这就很纳闷了。

于是又想到一个问题,是不是vivi编译成ko,导致一些变量的偏移量和新的sdk的不同,所以决定打印一下这个结构体的大小

vivi加入下面的log

static int vidioc_reqbufs(struct file *file, void *priv,
                          struct v4l2_requestbuffers *p)
{
        struct vivi_dev *dev = video_drvdata(file);
        struct vb2_queue *q = &dev->vb_vidq;


        printk(KERN_ERR "%sn", __func__);
        printk(KERN_ERR "%s size = %dn", __func__, sizeof(struct vb2_queue));

        if (vb2_fileio_is_active(q))
                printk(KERN_ERR "q->fileio --------------n");
        return vb2_reqbufs(&dev->vb_vidq, p);
}

内核中加入如下log

int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
{
        int ret;
        printk(KERN_ERR "%sn", __func__);
        printk(KERN_ERR "%s size = %dn", __func__, sizeof(struct vb2_queue));
        ret = vb2_verify_memory_type(q, req->memory, req->type);
        printk(KERN_ERR "%s 1111n", __func__);
        return ret ? ret : vb2_core_reqbufs(q, req->memory, &req->count);
}

 测试打印信息如下

[   36.774267] vidioc_reqbufs size = 304
[   36.774283] vb2_reqbufs size = 432

大小变了,这就好办了,于是对比结构体,发现了如下的差异

struct vb2_queue {
	...
	struct device			*alloc_devs[VB2_MAX_PLANES];
        ...

	struct vb2_fileio_data		*fileio;
	...
}

原来的VB2_MAX_PLANES值为32,同步后新的值为64,所以说内核使用fileio和vivi并不是一个。

 

最后的结论就是,不要偷懒,如果使用新的内核,那么所有的程序都要在新的内核上编译,这样才不会出现这种问题。

最后

以上就是过时洋葱为你收集整理的记一次 VIDIOC_REQBUFS failed 问题Linux v4l2架构学习总链接的全部内容,希望文章能够帮你解决记一次 VIDIOC_REQBUFS failed 问题Linux v4l2架构学习总链接所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部