摄像头驱动3_虚拟驱动vivi彻底分析

时间:2022-03-19 23:36:05

1、上一节测试的摄像头驱动程序的缺陷

(1)依次装载驱动程序,出现错误如下

摄像头驱动3_虚拟驱动vivi彻底分析

(2)用dmesg命令查看详细输出(某些函数没有识别),可见我们的vivi.ko还依赖于其他驱动程序,上一节直接使用这些命令没有问题,是因为在做虚拟摄像头vivi之前。我们先接上USB摄像头,ubuntu里面自动给我们安装了其他驱动程序。所以在使用vivi的时候,没有出现问题。

摄像头驱动3_虚拟驱动vivi彻底分析

(3)sudo modprobe vivi  

这是安装ubuntu里面自带的vivi驱动程序,把它依赖的其他驱动程序也一起安装进来

(4)把内核自带的vivi去掉,安装上我们编译出来的vivi.ko,用自己的编译程序是因为

我们以后做实验的时候要用到自己编译的代码

摄像头驱动3_虚拟驱动vivi彻底分析

2、根据虚拟驱动vivi的使用过程彻底分析摄像头驱动

(1)分析使用过程,通过应用程序源码xawtv分析,建立sourceinsight工程

(2)快捷了解xawtv所涉及的调用,用strace工具获得所涉及的调用。把xawtv所涉及的系统调用记录在xawtv.log文件里面。

摄像头驱动3_虚拟驱动vivi彻底分析

接下来分析xawtv.log

摄像头驱动3_虚拟驱动vivi彻底分析

(3)打开xawtv.log文件,搜索关键词“/dev/video0”,结合内核版本的vivi.c来分析

// 1~7都是在v4l2_open里调用
1. open  //驱动句柄“4”
2. ioctl(4, VIDIOC_QUERYCAP

// 3~7 都是在get_device_capabilities(获得相关属性)里调用
3. for()
        ioctl(4, VIDIOC_ENUMINPUT   // 列举输入源,VIDIOC_ENUMINPUT/VIDIOC_G_INPUT/VIDIOC_S_INPUT不是必需的
4. for()
        ioctl(4, VIDIOC_ENUMSTD  // 列举标准(制式), 不是必需的
5. for()       
        ioctl(4, VIDIOC_ENUM_FMT // 列举格式

6. ioctl(4, VIDIOC_G_PARM
7. for()
        ioctl(4, VIDIOC_QUERYCTRL    // 查询属性(比如说亮度值最小值、最大值、默认值)

// 8~10都是通过v4l2_read_attr来调用的       
8. ioctl(4, VIDIOC_G_STD            // 获得当前使用的标准(制式), 不是必需的
9. ioctl(4, VIDIOC_G_INPUT         //获得输入
10. ioctl(4, VIDIOC_G_CTRL           // 获得当前属性, 比如亮度是多少

11. ioctl(4, VIDIOC_TRY_FMT          // 试试能否支持某种格式
12. ioctl(4, VIDIOC_S_FMT            // 设置摄像头使用某种格式


// 13~16在v4l2_start_streaming
13. ioctl(4, VIDIOC_REQBUFS          // 请求系统分配缓冲区
14. for()
        ioctl(4, VIDIOC_QUERYBUF         // 查询所分配的缓冲区
        mmap          //对于每一个缓冲区都得到地址、大小等信息,利用mmap来映射地址,让应用程序知道以后去哪个地址访问缓冲区
15. for ()
        ioctl(4, VIDIOC_QBUF             // 把缓冲区放入驱动程序的队列       
16. ioctl(4, VIDIOC_STREAMON             // 启动摄像头



// 17里都是通过v4l2_write_attr来调用的
17. for ()
        ioctl(4, VIDIOC_S_CTRL           // 设置属性
    ioctl(4, VIDIOC_S_INPUT              // 设置输入源
    ioctl(4, VIDIOC_S_STD                // 设置标准(制式), 不是必需的

// v4l2_nextframe > v4l2_waiton   
18. v4l2_queue_all
    v4l2_waiton   
        for ()
        {
            select(5, [4], NULL, NULL, {5, 0})      = 1 (in [4], left {4, 985979}) //查询到有没有数据,驱动程序有数据后,把应用程序唤醒,唤醒后应用程序调用DQBUF获得buffer信息,然后处理它,处理完后再次放入队列里面
            ioctl(4, VIDIOC_DQBUF                // de-queue, 把缓冲区从队列中取出
            // 处理, 之以已经通过mmap获得了缓冲区的地址, 就可以直接访问数据       
            ioctl(4, VIDIOC_QBUF                 // 把缓冲区放入队列
        }

(4)xawtv的几大函数: 1. v4l2_open
2. v4l2_read_attr/v4l2_write_attr    //读写属性
3. v4l2_start_streaming   //启动流
4. v4l2_nextframe/v4l2_waiton   //


3、一边修改vivi.c一边测试

(1)执行xawtv

摄像头驱动3_虚拟驱动vivi彻底分析

出现以下画面

摄像头驱动3_虚拟驱动vivi彻底分析

(2)点击画面右键出现属性菜单

摄像头驱动3_虚拟驱动vivi彻底分析