报错现象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;
}