虚拟摄像头驱动程序彻底分析

xawtv(虚拟摄像头)涉及的vivi驱动的系统调用。
步骤:
1.打开摄像头设备:open(“/dev/video0”, O_RDWR|O_LARGEFILE) = 4
2.查询 当前driver是否合乎规范:ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0xbfaccd44) = 0
3.获得摄像头所提供数据的格式:ioctl(4, VIDIOC_G_FMT or VT_SENDSIG, 0xbfaccc78) = 0
4.for循环列举出摄像头所支持的格式:ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0xbfaccbec) = 0(非必须的)
5.查询 当前driver是否合乎规范,列举性能:ioctl(4, VIDIOC_QUERYCAP
6.获取当前使用源:ioctl(4, VIDIOC_G_INPUT, 0xbfacca2c) = 0(非必须的)
7.列举所有的输入源:ioctl(4, VIDIOC_ENUMINPUT, 0xbfacca2c) = 0(非必须的)
8.查询属性,比如亮度和对比度:ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0xbfacca78) = -1 EINVAL (Invalid argument)
9.ioctl(4, VIDIOC_QUERYCAP or VT_OPENQRY, 0x9b40998) = 0
10.for循环查询到底有多少个输入点:ioctl(4, VIDIOC_ENUMINPUT, 0x9b40acc) = 0
11.for循环列举标准(制式):ioctl(4, VIDIOC_ENUMSTD, 0x9b40f8c) = 0
12.for循环列举图片数据的格式:ioctl(4, VIDIOC_ENUM_FMT or VT_SETMODE, 0x9b4138c) = 0
13.获取参数:ioctl(4, VIDIOC_G_PARM, 0x9b40a00) = 0
14.for循环查询属性(比如亮度值最小值/最大值/默认值):ioctl(4, MATROXFB_TVOQUERYCTRL or VIDIOC_QUERYCTRL, 0x9b41b8c) = 0
15.获得当前使用的标准:ioctl(4, VIDIOC_G_STD, 0xbfacce08) = 0
16.列出当前使用的通道:ioctl(4, VIDIOC_G_INPUT, 0xbfacce1c) = 0
17.当前所使用的属性:ioctl(4, MATROXFB_G_TVOCTRL or VIDIOC_G_CTRL, 0xbfacce14) = 0
18.尝试能否 支持某种格式:ioctl(4, VIDIOC_TRY_FMT, 0x9b42ca4) = 0
19.如果支持某种格式,设置摄像头使用某种格式:ioctl(4, VIDIOC_S_FMT or VT_RELDISP, 0xbfacc754) = 0
20.请求系统分配多个缓冲区:ioctl(4, VIDIOC_REQBUFS or VT_DISALLOCATE, 0x9b42d80) = 0
21.查询系统所分配的缓冲区:ioctl(4, VIDIOC_QUERYBUF or VT_RESIZE, 0x9b42d94) = 0
22.for循环把缓冲区放入队列:ioctl(4, VIDIOC_QBUF, 0x9b42d94) = 0
23.启动摄像头:ioctl(4, VIDIOC_STREAMON, 0xbfacca2c) = 0
24.for循环设置属性:ioctl(4, MATROXFB_S_TVOCTRL or VIDIOC_S_CTRL, 0xbfacce10) = 0
25.设置输入源:ioctl(4, VIDIOC_S_INPUT, 0xbfacce84) = 0
26.设置标准(制式)ioctl(4, VIDIOC_S_STD, 0x9b40f90) = 0
26.for循环
①查看队列中的缓冲区是否有数据,有数据就取出数据: select(5, [4], NULL, NULL, {5, 0}) = 1 (in [4], left {4, 985979})
②把缓冲区从队列中取出ioctl(4, VIDIOC_DQBUF, 0xbfaccd00) = 0
③处理数据
⑤把缓冲区放入队列ioctl(4, VIDIOC_QBUF, 0x9b42d94) = 0

虚拟摄像头驱动程序的数据如何获得:
应用程序通过调用REQBUFS请求系统分配缓冲区,调用QUERYBUF查询缓冲区。调用mmap,告诉应用程序在哪个地址访问缓冲区。调用QBUF将缓冲区放入驱动程序中的某个队列中。调用STREAMON启动摄像头。调用select程序查询缓冲区是否有数据。如果驱动程序有数据之后,就会唤醒应用程序,唤醒完应用程序后,应用程序就会调用DQBUF,将缓冲区从队列中取出,获得缓冲区数据,进行处理。处理完后再将缓冲区放回队列。

重点函数:

   1.v4l2_open打开摄像头设备,get_device_capabilities(h)获得摄像头属性
    2. v4l2_read_attr/v4l2_write_attr(读/写属性)
    3. v4l2_start_streaming(申请buf)
    4. v4l2_nextframe/v4l2_waiton

摄像头驱动程序必需的11个ioctl:
// 表示它是一个摄像头设备
.vidioc_querycap = vidioc_querycap,

/* 用于列举、获得、测试、设置摄像头的数据的格式 */
.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,

/* 缓冲区操作: 申请/查询/放入队列/取出队列 */
.vidioc_reqbufs       = vidioc_reqbufs,
.vidioc_querybuf      = vidioc_querybuf,
.vidioc_qbuf          = vidioc_qbuf,
.vidioc_dqbuf         = vidioc_dqbuf,

// 启动/停止
.vidioc_streamon      = vidioc_streamon,
.vidioc_streamoff     = vidioc_streamoff,    

怎么写摄像头驱动程序:

  1. 分配video_device:video_device_alloc
  2. 设置
    .fops
    .ioctl_ops (里面需要设置11项)
    如果要用内核提供 的缓冲区操作函数,还需要构造一个videobuf_queue_ops
  3. 注册: video_register_device

本文章源于韦东山嵌入式

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
09-20 404
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值