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. Spring AOP小记

    一.概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导 ...

  2. spring中Bean对象的生命周期

    经过测试对于具体的一个Bean,执行的流程应该是: 1.实例化: 常见的有构造(有参.无参)实例化.静态工厂(方法是静态,通过类名.方法返回获取).实例工厂(专门有个类负责生产对象,需要在bean中配 ...

  3. python数据类型之元组、字典、集合

    python数据类型元组.字典.集合 元组 python的元组与列表类似,不同的是元组是不可变的数据类型.元组使用小括号,列表使用方括号.当元组里只有一个元素是必须要加逗号: >>> ...

  4. 文件锁FileLock

    1.文件锁的定义 FileLock是文件锁,进程锁,用于进程间并发,控制不同程序(JVM)对同一文件的并发访问. FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w) ...

  5. Shell与脚本

    shell是Linux操作系统的用户接口,我们经常需要编写脚本让操作系统自动执行一系列指令的需求,本文将简单介绍开发shell脚本的所需的语言特性. shell脚本是指令序列,其指令可以直接在终端中执 ...

  6. BZOJ 2653: middle [主席树 中位数]

    传送门 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右 ...

  7. Python高级用法总结

    Python很棒,它有很多高级用法值得细细思索,学习使用.本文将根据日常使用,总结介绍Python的一组高级特性,包括:列表推导式.迭代器和生成器.装饰器. 列表推导(list comprehensi ...

  8. Xshell配置SSH秘钥登录

    秘钥生成 生成公钥 工具 -> 新建用户秘钥生成向导 -> 下一步 -> 点击下一步,输入密码: 点击下一步 点击保存为文件,完成. 生成私钥 工具 -> 用户秘钥管理者 选中 ...

  9. IOS设备设计完整指南

    作为初学者,常常不知如何下手设计,IOS应用UI设计中碰到的种种基础小问题,在此都将一一得到解答.这份完整的设计指南将带你快速上手,为IOS设计出优雅的应用吧. 关于此设计指南 此设计指南描述的是如何 ...

  10. Docker安装Jenkins

    1.下载镜像 docker pull jenkins 2.生成一个容器 docker run -d --name myjenkins -p 8081:8080 -p 50000:50000  --vo ...