报错记录3:imx6ull适配ov2640摄像头无法获取默认摄像头分辨率与格式参数
文章目录
- 报错现象1
- 报错原因
- 解决方法
- 报错现象2
- 原因
- 解决方法
报错现象1
应用在设备启动后首次调用ioctl(fd, VIDIOC_G_FMT, &dev->cur_fmt);
获取摄像头默认参数时,获取到的值全为零
报错原因
mx6s_capture驱动中,VIDIOC_G_FMT
命令对应的接口为mx6s_vidioc_g_fmt_vid_cap
,此接口中,参数从csi_dev
中获取,但首次启动,在没有调用VIDIOC_S_FMT
前,csi_dev
参数中关于分辨率与视频格式的参数初始为0,因此函数返回的数据都为0。
static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,struct v4l2_format *f)
{struct mx6s_csi_dev *csi_dev = video_drvdata(file);WARN_ON(priv != file->private_data);f->fmt.pix = csi_dev->pix;return 0;
}
解决方法
解决方法就是在此接口中,调用ov2640驱动中的ov2640_g_fmt
接口,获取当前真实的参数信息,并将其返回给上层应用。
修改后的函数如下
static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,struct v4l2_format *f)
{struct mx6s_csi_dev *csi_dev = video_drvdata(file);struct v4l2_subdev *sd = csi_dev->sd;struct v4l2_mbus_framefmt mbus_fmt;struct mx6s_fmt *fmt;int ret;WARN_ON(priv != file->private_data);ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);if (ret == 0) {csi_dev->pix.width = mbus_fmt.width;csi_dev->pix.height = mbus_fmt.height;csi_dev->pix.field = mbus_fmt.field;fmt = format_by_mbus(mbus_fmt.code);if (!fmt) {dev_err(csi_dev->dev, "mbus (0x%08x) invalid.\n", mbus_fmt.code);} else {csi_dev->pix.pixelformat = fmt->pixelformat;}}f->fmt.pix = csi_dev->pix;return 0;
}
报错现象2
应用层在调用ioctl(fd, VIDIOC_G_FMT, &dev->cur_fmt);
接口时,无法返回修改后的视频流格式pixelformat
参数,pixelformat
参数会被清零。
原因
其原因为应用层调用VIDIOC_S_FMT
命令后,没有将当前的格式信息更新到csi_dev
参数中,造成VIDIOC_G_FMT
命令无法获取到真实的参数信息,VIDIOC_S_FMT
对应的驱动层调用接口为mx6s_vidioc_s_fmt_vid_cap
, 此接口在mx6s_vidioc_try_fmt_vid_cap
中,设置摄像头的分辨率与格式等参数,同时会将设置后的参数值通过实参f
反出来,但是调用完成后,代码并没有将pixelformat
的数据写入。
解决方法
修改mx6s_vidioc_s_fmt_vid_cap
函数,将真实的格式参数更新到csi_dev
中,修改后的函数如下。
static int mx6s_vidioc_s_fmt_vid_cap(struct file *file, void *priv,struct v4l2_format *f)
{struct mx6s_csi_dev *csi_dev = video_drvdata(file);int ret;ret = mx6s_vidioc_try_fmt_vid_cap(file, csi_dev, f);if (ret < 0)return ret;csi_dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);csi_dev->mbus_code = csi_dev->fmt->mbus_code;csi_dev->pix.width = f->fmt.pix.width;csi_dev->pix.height = f->fmt.pix.height;csi_dev->pix.sizeimage = f->fmt.pix.sizeimage;csi_dev->pix.field = f->fmt.pix.field;csi_dev->type = f->type;dev_dbg(csi_dev->dev, "set to pixelformat '%4.6s'\n",(char *)&csi_dev->fmt->name);/* Config csi */mx6s_configure_csi(csi_dev);return 0;
}