首页 > 代码库 > 远程视频监控之驱动篇(摄像头)
远程视频监控之驱动篇(摄像头)
转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/38515279
一.linux摄像头驱动框架
二.UVC介绍
UVC是USB video class的简称,图像产品在不需要安装任何的驱动程序下即插即用。我们通常所说的免驱摄像头。
免驱并不是说没有,而是大家硬件上都支持UVC这个规范,所以linux中有了一个通用的驱动。所以你再插上你的摄像头就不用下载驱动了,自动加载。
三.驱动分析
1.驱动的注册:
驱动在\drivers\media\video\uvc\uvc_driver.c 大家对照着看。
入口函数:uvc_init(void)
分配和设置: struct uvc_driver uvc_driver
注册: usb_register(&uvc_driver.driver);
我们下面将主要把经历放在分配和设置中:
struct uvc_driver uvc_driver = { .driver = { .name = "uvcvideo", .probe = uvc_probe, .disconnect = uvc_disconnect, .suspend = uvc_suspend, .resume = uvc_resume, .reset_resume = uvc_reset_resume, .id_table = uvc_ids, .supports_autosuspend = 1, }, };
我们先从简单的开始支持的id列表:.id_table = uvc_ids,
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, //通用USB类,控制接口
如果有摄像头插入并且在支持(符合UVC规范),自动调用 .probe = uvc_probe,
v4l2_device_register(&intf->dev, &dev->vdev) //相当于初始化的作用
uvc_register_chains(dev)
uvc_register_terms(dev, chain)
uvc_register_video(dev, stream);
video_device_alloc(); //分配
vdev->v4l2_dev = &dev->vdev; //设置
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
video_register_device(vdev, VFL_TYPE_GRABBER, -1); //注册device向V4L2
__video_register_device(vdev, type, nr, 1, vdev->fops->owner)
vdev->cdev = cdev_alloc(); //分配
vdev->cdev->ops = &v4l2_fops; //设置
cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1) //注册字符设备
这就是从摄像头插入的一系列注册过程
2.应用程序的调用
上面我们是从底层驱动逆推到了注册字符驱动,下面我们将从应用层起来看整个调用过程
a. open
app: open("/dev/video0",....)
---------------------------------------------------
drv: v4l2_fops.v4l2_open
vdev = video_devdata(filp); // 根据次设备号从数组中得到video_device
vdev->fops->open //即调用uvc_fops的open
uvc_v4l2_open
b. read
app: read ....
---------------------------------------------------
drv: v4l2_fops.v4l2_read
struct video_device *vdev = video_devdata(filp);
vdev->fops->read(filp, buf, sz, off); //即调用uvc_fops的read
uvc_v4l2_read
c. ioctl
app: ioctl
----------------------------------------------------
drv: v4l2_fops.unlocked_ioctl
v4l2_ioctl
struct video_device *vdev = video_devdata(filp);
vdev->fops->unlocked_ioctl(filp, cmd, arg); //即调用uvc_fops的unlocked_ioctl
uvc_v4l2_ioctl
video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
uvc_v4l2_do_ioctl
struct video_device *vdev = video_devdata(file)
根据APP传过来的命令标识符进行相应的操作具体操作有很多,我就不详细的讲了
附上常用命令标识符供大家看代码时候参考:
- VIDIOC_REQBUFS:分配内存
- VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
- VIDIOC_QUERYCAP:查询驱动功能
- VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
- VIDIOC_S_FMT:设置当前驱动的频捕获格式
- VIDIOC_G_FMT:读取当前驱动的频捕获格式
- VIDIOC_TRY_FMT:验证当前驱动的显示格式
- VIDIOC_CROPCAP:查询驱动的修剪能力
- VIDIOC_S_CROP:设置视频信号的边框
- VIDIOC_G_CROP:读取视频信号的边框
- VIDIOC_QBUF:把数据从缓存中读取出来
- VIDIOC_DQBUF:把数据放回缓存队列
- VIDIOC_STREAMON:开始视频显示函数
- VIDIOC_STREAMOFF:结束视频显示函数
- VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
参考:韦东山视频第三期