没有合适的资源?快使用搜索试试~ 我知道了~
首页Linux V4L2驱动详解
资源详情
资源评论
资源推荐

Video for Linux Two
(V4L2)
——驱动编写指南
原始翻译稿:Video4Linux2 (usr 技术社区 译文组)
原文地址:The Video4Linux2
整理:Tekkaman Ninja
2012-8-17
声明:本文是基于 http://lwn.net/网站上的经典系列文章《Video4Linux2》的翻译整理。
原始翻译来自 usr 技术社区 译文组和雷宏亮的博文。
本文因个人学习需要顺手做整理、修正,发布此文档仅为方便广大 Linux 爱好者。
Video for Linux Two(V4L2)——驱动编写指南
tekkamanninja.blog.chinaunix.net
第 1/30页
08/19/2012
Tekkaman Ninja

目录
一、 API 介绍 ......................................................................................................................3
二、 注册和 open() ................................................................................................................4
1. 视频设备注册 ...............................................................................................................5
2. open() 和 release() .........................................................................................................5
三、 基本 ioctl()处理 .............................................................................................................7
四、 输入和输出 ..................................................................................................................9
1. 视频标准 .....................................................................................................................9
2. 输入 ..........................................................................................................................10
3. 输出 ..........................................................................................................................11
五、 颜色与格式 ................................................................................................................12
1. 色域 ..........................................................................................................................12
2. 密集存储和平面存储 ....................................................................................................12
3. 四字符码 ...................................................................................................................13
4. RGB 格式 ..................................................................................................................13
5. YUV 格式 ..................................................................................................................14
6. 其他格式 ...................................................................................................................15
7. 格式描述 ...................................................................................................................15
六、 格式协商 ...................................................................................................................16
七、 基本的帧 I/O ..............................................................................................................19
1. read() 和 write() ..........................................................................................................19
2. 流参数 .......................................................................................................................19
八、 流 I/O ........................................................................................................................22
1. v4l2_buffer 结构体 .......................................................................................................22
2. 缓冲区设定 ................................................................................................................24
3. 将缓冲区映射到用户空间 ..............................................................................................25
4. 流 I/O ........................................................................................................................26
九、 控制 ..........................................................................................................................28
Video for Linux Two(V4L2)——驱动编写指南
tekkamanninja.blog.chinaunix.net
第 2/30页
08/19/2012
Tekkaman Ninja

一、 API 介绍
笔者最近有机会写了一个用于“One Laptop Per Child”项目中的摄像头驱动。这个驱动使用了为此目的而
设计的内核 API:the Video4Linux2 API。在写这个驱动的过程中,笔者发现了一个惊人的问题:这个 API
的文档工作做得并不是很好,而实际上用户层的文档则写得相当不错。为了补救这一现状,LWN 将在未来
的内个月里写一系列文章,告诉大家如何写 V4L2 接口的驱动。
V4L2 有一段历史了。大约在 1998 的秋天,它的光芒第一次出现在 Bill Dirks 的眼中。经过长足的发展,
它于 2002 年 11 月,在发布 2.5.46 时,融入了主线内核之中。然而直到今天,仍有一部分内核驱不支持新
的 API,这种新旧 API 的转换工作仍在进行。同时,V4L2 API 也在发展,并在 2.6.18 版本中进行了一些重
大的改变。支持 V4L2 的应用依旧相对较少。
V4L2 旨在支持多种设备,它们之中只有一部分在本质上是真正的视频设备:
video capture interface (影像捕获接口)从调谐器或摄像头上获取视频数据。对很多人来讲,影
像捕获(video capture) 是 V4L2 的基本应用。由于笔者在这方面的最有经验,这一系列文章也趋
于强调视频捕获 API,但 V4L2 的应用不限于此。
video output interface (视频输出接口)允许驱动 PC 外设,使其向外输出视频图像,而这可能通
过电视信号的形式。
捕获接口还有一个变体,存在于 video overlay interface(视频覆盖接口)之中。它的工作是方便
视频显示设备直接从捕获设备上获取数据。视频数据直接从捕获设备传到显示设备,无需经过
CPU。
VBI interfaces (Vertical blanking interval interface:垂直消隐接口)提供垂直消隐期的数据接入。
这个接口包括 raw 和 sliced 两种接口,其分别在于硬件中处理的 VBI 数据量。
radio interface (广播接口) 用于从 AM 或 FM 调谐器中获取音频数据。
也可能出现其它种类的设备。V4L2 API 中还有一些关于编解码器和效果设备的桩函数(stub),他们都
用来转换视频数据流。然而这部分还尚未形成规范,更不说应用了。还有“teletext”和”radio data system”的接
口,他们目前在 V4L1 API 中实现。他们没有移动到 V4L2 的 API 中来,而且目前也没有这方面的计划。
视频驱动与其他驱动不同之处在于它的配置方式多种多样。因此大部分 V4L2 驱动都有一些特定的代
码,好让应用可以知道给定的设备有什么功能,并配置设备,使其按期望的方式工作。V4L2 的 API 定义了
几十个回调函数,用来配置如调谐频率、窗口和裁剪、帧速率、视频压缩、图像参数(亮度、对比度…)、
视频标准、视频格式等参数。这一系列文章的很大部分都要用来考察这些配置的过程。
然后,还有一个小任务,就是有效地在视频频率下进行 I/O 操作。V4L2 定义了三种方法来在用户空间
和外设之间移动视频数据,其中有些会比较复杂。视频 I/O 和视频缓冲层,将会分成两篇文章来写,它们是
用来处量一些共性的任务的。
随后的文章每几周发一篇,都会加入到下面的列表中。
Part 2: 注册和 open()
Part 3: 基本 ioctl()处理
Part 4: 输入和输出
Part 5a: 颜色与格式
Part 5b: 格式协商
Part 6a: 基本的帧 I/O
Part 6b: 流 I/O
Part 7: 控制
Video for Linux Two(V4L2)——驱动编写指南
tekkamanninja.blog.chinaunix.net
第 3/30页
08/19/2012
Tekkaman Ninja

二、 注册和 open()
这篇文章是 LWN 写 V4L2 接口的设备驱动系列文章的第二篇。没看过介绍的,也许可以从那篇开始看。
这一期文章将关注 Video for Linux 驱动的总体结构和设备注册过程。
开始之前,有必要提一点,那就是对于搞视频驱动的人来说,有两份资料是非常有价值的:
V4L2 API 规范。这份文档涵盖了用户空间视角下的 API,但在很大程度上,V4L2 驱动直接实现
的就是那些 API。所以大部分结构体是相同的,而且 V4L2 调用的语义也表述很很明了。打印一份
出来(可以考虑去掉自由文本协议的文本内容,以保护树木),放在触手可及的地方。
内核代码中的 vivi 驱动,即 drivers/media/video/vivi.c.这是一个虚拟驱动。它可以用来测试,却不
使用任何实际硬件。这样,它就成一个教人编写 V4L2 驱动的极佳实例。
首先,每个 V4L2 驱动都要包含一个必须的头文件:
#include <linux/videodev2.h>
大部分所需的信息都在这里。作为一个驱动作者,当挖掘头文件的时候,你可能也得看看
include/media/v4l2-dev.h,它定义了许多你将来要打交道的结构体。
一个视频驱动很可能要有处理 PCI 或 USB 总线,这里我们不会花时间来触及这些东西。通常会有一个
内部 I2C 接口,我们在本系列的后续文章中会接触到它。然后还有一个 V4L2 子系统接口,这个子系统是
围绕 video_device 结构体建立的,它代表一个 V4L2 设备。讲解这个结构体中的一切,将会是这个系列中几
篇文章的主题。这里我们先对这个结构体有一个概览。
video_device 结构体的 name 字段是这类设备的名字,它将出现在内核日志和 sysfs 中出现。这个名字
通常与驱动名称相同。
设备类型则由两个字段来描述。第一个字段(type)似乎是从 V4L1 的 API 中遗留下来的,它可以下列
四个值之一:
VFL_TYPE_GRABBER 表明是一个图像采集设备–包括摄像头、调谐器,诸如此类。
VFL_TYPE_VBI 代表的设备是从视频消隐时间段取得信息的设备。
VFL_TYPE_RADIO 代表无线电设备。
VFL_TYPE_VTX 代表视传设备。
如果你的设备支持不只一个上面提到的功能,那就要为每个功能注册一个 V4L2 设备。而在 V4L2 中,
每个注册的设备都可以按照它实际支持的各种模式来调用(就是说,你要为一个物理设备创建不多个设备
节点,但你却可以调用任意一个设备节点,来实现这个物理设备支持的任何功能)。实质上,在 V4L2 中,
你实际上只需一个设备,而注册多个 V4l2 设备只是为了与 V4l1 兼容。
第二个字段是 type2,它以掩码的形式对设备的功能提供了更详尽的描述。它可包含如下值:
VID_TYPE_CAPTURE 视频数据捕获
VID_TYPE_TUNER 不同的频率调整
VID_TYPE_TELETEXT 字幕抓取
VID_TYPE_OVERLAY 可将视频数据直接覆盖到显示设备的帧缓冲区
VID_TYPE_CHROMAKEY 一种特殊的覆盖能力,覆盖的仅是帧缓冲区中像素值为某特定值的区域
VID_TYPE_CLIPPING 剪辑覆盖数据
VID_TYPE_FRAMERAM 使用帧缓冲区中的内存空间
VID_TYPE_SCALES 视频缩放
VID_TYPE_MONOCHROME 纯灰度设备
VID_TYPE_SUBCAPTURE 捕获图像子区域
Video for Linux Two(V4L2)——驱动编写指南
tekkamanninja.blog.chinaunix.net
第 4/30页
08/19/2012
Tekkaman Ninja

VID_TYPE_MPEG_DECODER 支持 mpeg 码流解码
VID_TYPE_MPEG_ENCODER 支持编码 mpeg 码流
VID_TYPE_MJPEG_DECODER 支持 mjpeg 解码
VID_TYPE_MJPEG_ENCODER 支持 mjpeg 编码
V4L2 驱动还要初始化的一个字段是 minor,它是你想要的子设备号。通常这个值都设为-1,这样会让
video4linux 子系统在注册时自动分配一个子设备号。
在 video_device 结构体中,还有三组不同的函数指针集。第一组只包含一个函数,那就是 release(),如
果驱动没有 release()函数,内核就会抱怨(笔者发现一个件有趣的事,就是这个抱怨涉及到冒犯一篇 LWN
文章作者)。release()函数很重要:由于多种原因,对 video_device 的引用可以在最后一个应用关闭文件描述
符后很长一段时间依然保持。它们甚至可以在设备己经注销后依然保持。因此,在 release()函数调用前,释
放这个结构体是不安全的。所以这个函数通常要包含一个简单的 kfree()调用。
video_device 的 file_operations
[
注
]
结构体包含都是常规的函数指针。视频设备通常都包括 open()和
release()函数。注意:这里所说的 release 函数并非上面所讲到的同名的 release()函数,这个 release() 函数只
要设备关闭就要调用。通常都还要有 read()和 write()函数,这取决于设备的功能是输入还是输出。然而我
们要注意的是,对于视频流设备而言,传输数据还有别的方法。多数处理视频流数据的设备还需要实现 poll()
和 mmap();而且每个 V4L2 设备都要有 ioctl()函数,但是也可以使用 V4L2 子系统的 video_ioctl2();
第三组函数存在于 video_device 结构体本身里面,它们是 V4L2 API 的核心。这组函数有几十个,处理
不同的设备配置操作、流输入输出和其他操作。
最后,从一 开 始 就 要知道的一个字 段 就 是 debug。可以把它设成是 V4L2_DEBUG_IOCTL 或
V4L2_DEBUG_IOCTL_ARG(或是两个都设,这是个掩码),可以生成很多调试信息,它们可以帮助迷糊
的程序员找到毛病,知道驱动和应用之间的沟通障碍在哪。
译者注:新内核中,
video_device
结构体中的这个
file_operations
应该指的是
v4l2_file_operations
。
1. 视频设备注册
一旦 video_device 己经配置好,就可以用下面的函数注册了:
int video_register_device(struct video_device *vfd, int type, int nr);
这里 vfd 是设备的结构体(video_device),type 的值与它的 type 字段值相同,nr 是期望的子设备号(为
-1 则注册时自动分配)。成功则返回值为 0。若出错,则返回的是负的出错码。我们必须意识到:通常设备
一旦注册,它的函数可能就会被立即调用,所以在一切准备就绪前,不要调用 video_register_device()。
设备注销函数为:
void video_unregister_device(struct video_device *vfd);
请继续关注本系列的下篇文章,我们将会看看这些函数的具体实现。
2. open() 和 release()
每个 V4L2 设备都需要 open()函数,其原型也与常规的相同。
int (*open)(struct inode *inode, struct file *filp);
open()函数要做的第一件事是通过给定的 inode 找到内部设备,就是通过找到 inode 中存存储的子设备
号来完成的。这里还可以实现一定程度的初始化,如果有掉电选项的话,此时恰好可以用来开启硬件电源。
V4L2 规范还定义了一些相关的惯例。其一是:根据其设计,文件描述符可以在给定的任何时间重复打
开。这样设定的目的是当一个应用在显示(或是产生)视频信号时,另一个应用可以改变控制值。所以,
Video for Linux Two(V4L2)——驱动编写指南
tekkamanninja.blog.chinaunix.net
第 5/30页
08/19/2012
Tekkaman Ninja
剩余29页未读,继续阅读
















安全验证
文档复制为VIP权益,开通VIP直接复制

评论0