对应应用程序(xawtv),摄像头的操作过程:
①open打开摄像头设备(v4l2_open)
②获取或者设置摄像头的属性参数(v4l2_read_attr/v4l2_write_attr)
③准备缓冲区,启动流传输(v4l2_star_streaming)
④重复等待数据,处理数据,准备新缓冲区(v4l2_nextframe,v4l2_waiton)
一个摄像头(video_device)的ioctl(①~⑤是设置属性参数,后面的是缓冲区处理):
①摄像头标签,指明这是个摄像头设备(vidio_querycap)<必须的>
②视频输入源,对于一个设备可以有多个输入源camera1、camera2等等(vidioc_enum_input, vidioc_s_input,vidio_g_input)<不是必须的>
③摄像头的TV制式,只针对模拟摄像头(vidioc_s_std)<不是必须的>
④摄像头数据的格式(vidioc_enum_fmt_cap,vidioc_try_fmt_cap,vidioc_s_fmt_cap,vidioc_g_fmt_cap)<枚举操作不是必须,其余必须>
⑤摄像头的白平衡、色彩等参数(vidioc_query_ctrl,vidioc_s_ctrl,vidioc_g_ctrl)<不是必须的>,没有这些函数,色彩调节只能通过软件完成
⑥缓冲区的申请、查询、入列、出列(vidioc_querybuf,vidioc_reqbuf,vidioc_qbuf,vidioc_dqbuf)<必须的>
⑦流停止与启动(vidioc_streamon,vidioc_streamoff)
流数据的处理
video_device.open函数创建了两个队列,底层硬件操作占用一个,另外一个让上层app使用
通过ioctl缓冲区操作申请创建数据缓冲区,每个缓冲区需要至少能够存放一帧图像(对于底层usb驱动还需要通过分包完成一帧图像的传输)
video.mmap将应用程序的虚拟内存地址跟驱动层中创建的缓冲区地址相关联
for循环
{
应用程序将空闲缓冲区同时放入之前创建的两个缓冲区队列中
上层应用调用video_device.select,进入阻塞,等待数据唤醒
驱动中的硬件完成一帧图像数据捕获后,触发中断,从底层专用的队列中取出空缓冲区,并且填充数据后,并且唤醒用户休眠进程
应用程序从自己专用的队列中取出第一个缓冲区,进行数据处理
}
对于v4l2_fops直接调用video_fops,所以驱动程序中三个主要的ops,:
①video_fops
②由于fops->ioctl = video_ioctl2,所以需要提供ioctl_ops
③由于ioctl_ops中的缓冲区操作函数调用了内核提供的操作函数,所以在open缓冲区队列初始化时除了提供自旋锁,还需要有videobuf_ops,如果驱动程
序自行实现ioctl_ops中的缓冲区操作,则videobuf_ops可以省略