概述
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架构学习总链接所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复