V4L2(video for linux) 可以支持多种设备,它可以有以下5种接口:

1、视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;

2、视频输出接口(video output interface):可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备;

3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU;

4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;

5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;

V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.

一、V4L2的移植

V4L2提供了三种不同的API来传输外围设备和用户空间的数据。下面就vivi(drivers/media/video/vivi.c)来讲解一个V4L2驱动的编写。注意它是一个虚拟的设备驱动,没有与实际的硬件打交道。

    1、分析几个重要数据结构:

     vivi.c包含头文件v4l2-device.h和v4l2-ioctl.h,其中v4l2-device.h中包含了v4l2-subdev.h,v4l2-subdev.h中又包含了v4l2-common.h,v4l2-common.h中包含了v4l2-dev.h。

在v4l2-dev.h中定义了结构体video_device和v4l2_file_operations;

在v4l2-ioctl.h中定义了结构体v4l2_ioctl_ops;

在v4l2-device.h中定义了结构体v4l2_device;

1) vivi_fops

static const struct v4l2_file_operations vivi_fops = {

.owner           = THIS_MODULE,

.open           = vivi_open,

.release        = vivi_close,

.read           = vivi_read,

.poll        = vivi_poll,

.ioctl          = video_ioctl2, /* V4L2 ioctl handler */

.mmap           = vivi_mmap,

};

2) vivi_ioctl_ops

static const struct v4l2_ioctl_ops vivi_ioctl_ops = {

.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_s_std         = vidioc_s_std,

.vidioc_enum_input    = vidioc_enum_input,

.vidioc_g_input       = vidioc_g_input,

.vidioc_s_input       = vidioc_s_input,

.vidioc_queryctrl     = vidioc_queryctrl,

.vidioc_g_ctrl        = vidioc_g_ctrl,

.vidioc_s_ctrl        = vidioc_s_ctrl,

.vidioc_streamon      = vidioc_streamon,

.vidioc_streamoff     = vidioc_streamoff,

#ifdef CONFIG_VIDEO_V4L1_COMPAT

.vidiocgmbuf          = vidiocgmbuf,

#endif

};

3) vivi_template

static struct video_device vivi_template = {

.name             = "vivi",

.fops           = &vivi_fops,

.ioctl_ops       = &vivi_ioctl_ops,

.minor            = -1,

.release    = video_device_release,

.tvnorms              = V4L2_STD_525_60,

.current_norm         = V4L2_STD_NTSC_M,

};

其中函数vivi_xxx和vidioc_xxx都是在vivi.c中实现的。如果要基于某个硬件来实现V4L2的接口,那这些函数就需要调用硬件的驱动去实现。

4) vivi_dev

struct vivi_dev {

    struct list_head           vivi_devlist; //内核双向链表,在内核数据结构里有描述

    struct semaphore           lock;   //信号量,防止竞态访问

    int                        users;  //用户数量计数

    /* various device info */

    unsigned int               resources;

    struct video_device        video_dev; //这个成员是这个结构的核心,用面向对象的话来说就是基类

    struct vivi_dmaqueue       vidq;       //DMA队列

    /* Several counters */

    int                        h,m,s,us,jiffies;   //定时器定义

    char                       timestr[13];     //其它一些资源变量.

};

    像这样变义的结构在Linux C 中很普遍,这也是利用C来实现面向对象编程的强大方法。建立这个结构对象之后,所有的操作都是基于这个结构,或者这个结构派生出的来的其它结构。

    5) vivi_fh

struct vivi_fh {

    struct vivi_dev            *dev;

    /* video capture */

    struct vivi_fmt            *fmt;

    unsigned int               width,height;

    struct videobuf_queue      vb_vidq;

    enum v4l2_buf_type         type;

};

    这个结构即是vivi_dev结构的更深层次封装,基于那个结构加入了更多的描述信息,如视频制式、视频画面大小、视频缓冲队列等等。在open的时候,会把这个结构赋给file结构中的private_data域。在释放设备时注销.其它的像ioctl,mmap,read,write等等都会用到这个结构,其实整个模块的编写的cdev差不多。只是视频设备的基类是video_device,而字符设备的基类是cdev而已。

    2、数据传输方式:

    在设备与应用程序之间有三种数据传输方式:

    1)read与write这种方式,它像其它设备驱动一样,但是这种方式很慢,对于数据视频流不能满足其要求;

2)直接的内存访问,可以通过其映射方式来传输(IO数据流,交换指向缓冲区指针的方法);这是视频设备通常用的方法,采用mmap()的方法,即有内核空间里开辟内存,再在程序里把这部分的内存映射到程序空间。如果有设备内存,即直接映射到设备的内核,这种性能更高。

    3)异步IO口访问,但是这种方法在V4L2模块中还没有实现。(重要:需要确认)

     vivi中的mmap是利用第二种方法来实现的,这也是视频设备常用的方法:

static int

vivi_mmap(struct file *file, struct vm_area_struct * vma)

{

    struct vivi_fh *fh = file->private_data;

    int ret;

    dprintk (1,"mmap called, vma=0x%08lx/n",(unsigned long)vma);

    ret=videobuf_mmap_mapper(&fh->vb_vidq, vma);

    dprintk (1,"vma start=0x%08lx, size=%ld, ret=%d/n",

        (unsigned long)vma->vm_start,

        (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,

        ret);

    return ret;

}

    videobuf_mmap_mapper(&fh->vb_vidq, vma);  这个核心函数把设备的I/O内存或者设备内存映射到系统为它开辟的虚拟内存。

    3、操控设备的实现: ioctl

static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

    return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);  

}

    vivi_do_ioctl 这个函数里调用一些命令来设备V4L2模块中的一些结构参数来改变或者获取设备的参数

V4L2驱动的移植与应用(一)的更多相关文章

  1. V4L2驱动的移植与应用(二)

    二.V4L2的应用 下面简单介绍一下V4L2驱动的应用流程. 1.  视频采集的基本流程 一般的,视频采集都有如下流程: 2.  打开视频设备 在V4L2中,视频设备被看做一个文件.使用open函数打 ...

  2. V4L2驱动的移植与应用(二+三)【转】

    转自:http://blog.chinaunix.net/uid-10747583-id-298489.html 原文地址:http://blog.csdn.net/wxzking/archive/2 ...

  3. V4L2驱动的移植与应用(三)

    三.V4L2的demo capture.c是官方示例程序. capture.c 程序中的 process_image 函数: capture.c 程序主要是用来演示怎样使用 v4l2 接口,并没有对采 ...

  4. v4l2驱动编写篇【转】

    转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...

  5. WIFI驱动的移植 realtek 8188

    一般我们拿到的android源代码中wifi应用层部分是好的, 主要是wifi芯片的驱动要移植并添加进去. wifi驱动的移植, 以realtek的8188etv为例到官网下载相应的驱动, 解压后可以 ...

  6. 【Linux高级驱动】触摸屏驱动的移植

    触摸屏驱动的移植 流程 注意:看框架图 1.添加input.c组件 Device Drivers  ---> Input device support  --->  Generic inp ...

  7. V4L2驱动内核文档翻译(一)

    随着一些视频或者图像硬件的复杂化,V4L2驱动也越来越趋于复杂.许多硬件有多个IC,在/dev下生成多个video设备或者其他的诸如,DVB,ALSA,FB,I2C ,IR等等非V4L2的设备.所以, ...

  8. 2.1 摄像头V4L2驱动框架分析

    学习目标:学习V4L2(V4L2:vidio for linux version 2)摄像头驱动框架,分析vivi.c(虚拟视频硬件相关)驱动源码程序,总结V4L2硬件相关的驱动的步骤:  一.V4L ...

  9. v4l2驱动文档之——streaming IO【转】

    转自:http://blog.csdn.net/zoe6553/article/details/17715441 v4l2驱动编写篇第六B--流输入输出 在本系列文章的上一期中,我们讨论了如何通过re ...

随机推荐

  1. JS小练习1

    要求: 一.定义"改变颜色"的函数 二.定义"改变宽高"的函数 三.定义"隐藏内容"的函数 四.定义"显示内容"的函数 ...

  2. 一步一步从原理跟我学邮件收取及发送 9.多行结果与socket的阻塞

    前几篇的文章发表后,有网友留言说没有涉及到阻塞的问题吗?在 socket 的编程当中,这确实是个很重要的问题.结合目前我们文章的内容进度,我们来看看为什么说阻塞概念很重要. 接着上篇的内容,当我们发送 ...

  3. 记React+.NetCore API实现动态列导出

    1.效果演示 2.用到的第三方类库 前端:React,Dva,Antd 后端:ASP.NET CORE,System.Linq.Dynamic.Core,EPPlus.Core 3.基本思路 第一:E ...

  4. zookeeper 实现分布式锁

    主要是依赖临时节点的特性.数据存储到内存中效率高:例如有web1 web2 两台应用服务器 db1 db2两台db服务器  db互为主备,web1 web2 分别去修改db1 .有限db2库里张三的年 ...

  5. BZOJ 1951: [Sdoi2010]古代猪文 [Lucas定理 中国剩余定理]

    1951: [Sdoi2010]古代猪文 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 2194  Solved: 919[Submit][Status] ...

  6. 汽车之家店铺数据抓取 DotnetSpider实战[一]

    一.背景 春节也不能闲着,一直想学一下爬虫怎么玩,网上搜了一大堆,大多都是Python的,大家也比较活跃,文章也比较多,找了一圈,发现园子里面有个大神开发了一个DotNetSpider的开源库,很值得 ...

  7. 插上腾飞的翅膀:为asp.net core添加protobuf支持

    没时间解释了,快上车. 通过NuGet获取Zaabee.AspNetCoreProtobuf Install-Package Zaabee.AspNetCoreProtobuf 在Startup.cs ...

  8. docker设置固定ip地址

    Docker安装后,默认会创建下面三种网络类型 $ docker network ls NETWORK ID NAME DRIVER SCOPE 9781b1f585ae bridge bridge ...

  9. dig挖出DNS的秘密

    [最简单的dig用法] 最简单的dig用法,当然就是直接输入dig按回车. 1 2 3 4 5 6 $ dig   ; <<>> DiG 9.8.2rc1-RedHat-9.8 ...

  10. Mybatis查询,resultMap="Map" 查询数据有空值,导致整个map为空的问题

    解决方法,不要使用Map接收,使用HashMap或者LinkHashMap,都可以. resultMap="Map" 替换为: resultMap="HashMap&qu ...