虚拟摄像头vivi驱动分析

虚拟摄像头vivi驱动分析:

1.通过分析xawtv这个应用程序所涉及的系统调用来间接分析vivi的驱动程序。我们用运行时显示的信息作为切入点:strace -o xawtv.log xawtv 将运行xawtv后的打印信息保存入xawtv.log中,并且自动运行xawtv

2.xawtv的几大函数:

1.v4l2_open

2.v4l2_read_atrr/v4l2_write_attr

3.v4l2_start_streaming

4.v4l2_nextframe/v4l2_waiton

 

3.整体分析:xawtv调用一系列的ioctl函数已经相应的参数发送到驱动程序,vivi驱动对参数进行分析和处理,下面进行具体说明。

 

4.首先要说的是xawtv查询驱动中摄像头的属性capabilities,驱动中已经设置其为cap->capabilities=V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;//表示此驱动支持摄像头采集(CAPTURE),同时支持应用层调用ioctl函数进行的QBUF,DQBUF等涉及队列的数据操作,以及支持应用层调用read,write接口进行的数据操作这两种摄像头数据读取方式。

 

5.第二个ioctl命令是ENUM_INPUT 设置输入源。在xawtv界面中可以设置输入源,Video source:Camera0,camer1...。为使看见其他输入源的效果,可让vivi驱动中vivi.c文件中的vidioc_streamoff函数都返回0,即修改为:videobuf_streamoff(&fh->vb_vidq); return 0;即可。然后重新编译并加载驱动即可。然后点击应用程序的其他输入源也能显示了。总之,当我们的摄像头只有一个输入源时,用于选择输入源的操作函数可以省略,有VIDIOC_ENUMINPUT,VIDIOC_G_INPUT,VIDIOC_S_INPUT这三个ioctl命令。

 

6.VIDIOC_ENUMSTDVIDIOC_G_STD这些涉及标准制式的操作可以省略,底层中file_operations中的.tvnorms=V4L2_STD_525_60;

.current_norm=V4L2_STD_NTSC_M;//这些用于列举、设置、获得TV制式的操作可以省略,对图像显示没有影响。

 

7.用于列举、获得、测试、设置摄像头所提供的数据的格式的操作有:

.vidioc_enum_fmt_vid_cap=vidioc_enum_fmt_vid_cap,

.vidioc_g_fmt_vid_cap=vidioc_g_fmt_vid_cap,

.vidioc_try_fmt_vid_cap=vidioc_try_fmt_vid_cap,

.vidioc_s_fmt_vid_cap=vidioc_s_fmt_vid_cap,

这些操作是必不可少的,最好不要去掉。

 

8.缓冲区操作:申请、查询、放入队列、取出队列这些操作当然是必不可少的,这里就不说了。

 

9.查询、获得、设置属性操作来对亮度、对比度、白平衡这些摄像头数据进行操作。有vidioc_queryctrl,vidioc_g_ctrl,vidioc_s_ctrl这三个。

这些可以省略,省略后只是不能修改属性了。

 

10.启动摄像头命令vidioc_streamon,关闭摄像头命令vidioc_streamoff当然是必不可少的。

 

11.继续分析数据的获取过程:

1.请求分配缓冲区:ioctl(4,VIDIOC_REQBUFS); videobuf_reqbufs(队列,v4l2_requestbuffers);//第二个参数表示要分配多少个缓冲区,一般至少有2个缓冲区。队列在open函数里用videobuf_vmalloc_init函数中进行了初始化。这个IOCTL只是分配了缓冲区的头部信息,真正的缓存还没有分配。

2.查询映射缓冲区:应用层调用ioctl(4,VIDIOC_QUERYBUF);//获得缓冲区的数据格式、大小、每一行长度、高度信息,但是实际上驱动还并未分配内存。

应用层调用mmap函数后,驱动调用vivi_mmap函数,给缓冲区分配空间,这时才有实际的缓冲区。

3.把缓冲区放入队列:ioctl(4,VIDIOC_QBUF)。其中调用函数list_add_tail把缓冲区放入队列的尾部。

4.启动摄像头:ioctl(4,VIDIOC_STREAMON) 

5.用select查询是否有数据,没有则阻塞。驱动中有产生数据,唤醒进程。应用层从队列的头部获得缓冲区,如果没有数据则休眠。同时,驱动中的vivi_thread_tick函数中会创建一个内核线程,构造虚拟摄像头数据,每隔30毫秒唤醒进程,应用程序调用IOCTLvidioc_dqbuf来。

6.有数据后从队列中取出缓冲区:  ioctl(4,VIDIOC_DQBUF)

在队列里获得有数据的缓冲区,把它从队列中删掉,然后把这个缓冲区的状态返回给APP。应用程序根据VIDIOC_DQBUF所得到缓冲区状态,知道是哪一个缓冲区有数据,就去读对应的地址(该地址来自前面的mmap)。队列的处理总是从头开始,用完之后再放入尾部。

 

7.怎样写摄像头驱动:

1.分配video_device结构体

2.设置

.fops 

.ioctl_ops(里面有11)

如果要用内核提供的缓冲区操作函数,还需要构造一个videobuf_queue_ops结构体。

3.注册结构体

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值