转自http://blog.csdn.net/wuhzossibility/article/details/6638245
- Chapter 1 通用APICommon API Elements
Video for Linux Two API Specification
Revision 0.24
Michael H Schimek
mschimek@gmx.at
Bill Dirks
Hans Verkuil
Martin Rubli
V4L2 中文版 Made by鱼在飞(467350479) 个人翻译转载申明
v4l2全五章下载地址
Chapter 1. 通用APICommon API Elements
编程以支持一个V4l2的设备包含以下步骤
.打开设备
.改变设备的属性选择音频和视频输入视频的标准编码格式图片的亮度等
.协商数据格式
.协商输入/输出的方法
.输入/输出循环
.关闭设备
1.1. 打开和关闭设备Opening and Closing Devices
1.1.1. 设备命名(Device Naming)
V4L2以模块的方式在内核中实现可以被管理员手动的加载或者是当设备第一次打开时被加载。驱动模块被挂在内核模块"videodev"下。在这份文档中提供了辅助函数和一个通用的应用程序接口规范。
每个驱动加载时都会用主设备号81和次设备号0-255来注册一个或多个设备节点。该如何分配次设备号给这些个V4L2设备完全取决与系统管理员这主要是为了解决设备间的冲突为了区分不同的设备1。当选定次设备号后模块将会以"_nr"为前缀来命名特殊的设备文件名。举个例子来说,像"video_nr"就是代表视频采集设备的在内核中表示为/dev/video。数字则是和设备类型相关并基于次设备号的一个偏移2。
当驱动支持同一型号的多个设备时这时就可以赋予多个次设备号了并以逗号隔开
> insmod mydriver.o video_nr=0,1 radio_nr=0,1
在/etc/modules.conf 文件中可能是显示如下
alias char-major-81-0 mydriver
alias char-major-81-1 mydriver
alias char-major-81-64 mydriver
Options mydriver video_nr=0,1 radio_nr=0,1 ‚
当应用程序试图打开主设备号81次设备号0,1,64时会加载驱动"mydriver"
‚注册前两个视频采集设备时是从主设备号0开始的接着是1...一直到63而音频设备则是从次设备64开始的。
如果未显式给定次设备号那么模块将提供一个默认值。第四章将阐述不同型号设备的起始次设备号。显然次设备号必须是独一无二的。假如所请求的设备号正在使用时很明显起冲突的设备将不会被注册。
安装惯例系统管理员会根据主、次设备号在/dev目录下创建不同功用的特殊设备文件。文件名字则建议有别于列在第四章的V4L2设备名。
用命令mknod创建的字符设备拥有特权操作并且这些设备是不能通过主、次设备号打开的。这就意味着应用程序是不能可靠的扫描已加载或者是安装的驱动的。用户必须键入设备名或者应用程序会尝试默认的设备名。
在设备文件系统devfs下次设备号是被忽略的明显的在其下我们只要知道设备的功能主设备号就提供这样的作用。V4L2驱动会自动的在/dev/v4l目录下用默认的设备名创建所请求的设备文件。
1.1.2. 相关设备Related Devices
驱动通常都能支持许多相关的功能。有个例子说视频采集直接传输视频视频垂直消隐信号采集
都有着千丝万缕的联系这是因为这些功能都共享着起码在他们之间相同的视频输入视频采集头webcam和高频头可以看作是音视频采集头。
注V4L2所提供的接口
1. 视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.
2. 视频输出接口(video output interface):可以驱动计算机的外围视频图像设备--像可以输出电视信号格式的设备.
3. 直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU.
4. 视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号.
5. 收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流.
V4L和早前的V4L2版本视频采集和overlay是使用相同的设备名相同的次设备号但是却有别于VBIVertial Blanking Interval。实践表明这种方法拥有众多问题3更糟糕的是V4L的videodev模型是禁止同时多次打开设备的。
作为补救措施当前的V4L2版本是通过特定的名字和次设备号放宽了设备类型的概念。为了保持和旧的应用程序的兼容性驱动必须依旧注册不同的次设备号并制定一个默认的对应功能给这个设备major代表一类设备minor这是用来给内核区分一类设备的不同实例或者功能。这样major代表一个班级那么minor就是用来告诉校长这班级中的某个学生。但是如果驱动支持相关功能就必须在所注册的次设备号下实现这个功能就是说为了支持老版应用像mjpg-server你必须为这类设备提供一个minor以支持默认的功能但他有新的作用你也必须给予支持。在第四章提及的一些功能可以在打开的时候进行选择。
想象一下一个驱动支持视频采集直接视频传输视频间隔消隐信号和FM收音机。他用0,64,224这种编码格式是为保兼容性从V4L API中继承下来的次设备号注册了三个设备。不管/dev/video(81,0)或者/dev/vbi(81,224)是否处于打开状态应用程序都可以从这三种设备中选择某项功能。不通过编程就是说0直接用命令dd和cat/dev/video就可采集视频图片通过/dev/vbi来获得原始的视频间隔消隐信号。 /dev/radio81,64是一个不变的无线装置因而和视频部分的功能并没有联系。但是没有相互的关联并不意味着你可以同时使用它们。当你用open()调用时很有可能返回设备忙--EBUSY的错误代码。
除视频的输入输出外硬件可能也支持抽样甚至是回放功能VLC貌似就是这样的。如果真是这样那么这些功能会被实现为OSSOpen Sound System或者ALSA Advanced Linux Sound ArchitecturePCM设备最终可能是OSS或者的混合体。V4L2 API并未做任何假设来发现这些有相互关系的设备。
If you have an idea please write to the Video4Linux mailing list:
https://listman.redhat.com/mailman/listinfo/video4linux-list.
1.1.3. 并发打开Multiple Opens
通常V4l2设备可被多次打开的。当这被驱动支持时用户可以例子说嘛你可以设计一个面板程序比如有些按钮可以调节亮暗或者音量啊而与此同时另一个应用程序却正在采集音视频。换句话说面板程序就被比作了OSS或者ALSA混合应用了。当一个设备支持多项功能像采集啊且能同时直接接传输啊神马的Multiple Opens允许fork出进程或特定的应用程序达到并发的使用设备。
Multiple Opens是可选的驱动应该至少允许在没数据交换的情况下支持并发访问例子就是上面的面板程序。这意味着当设备正在使用中时open()可返回EBUSY错误代码ioctl()函数的初始化数据交换也就是VIDIOC_S_FMT ioctl,read(),write()函数亦是如此。
只不过打开一个V4L2设备并不允许互斥存取4。然而初始化数据交换赋予读和写数据的请求类型的权利。
也可以改变相关属性文件描述符。应用程序可以通过在1.3节描述的优先级机制请求额外的访问权限。
1.1.4. 共享数据流(Shared Data Streams)
V4L2驱动不应该支持在一个设备上通过拷贝缓冲对同一数据流进行多应用程序的读或写或者是时分复用亦或是其他相似的方法。非要这么干可以使用在用户空间的代理程序。如果驱动支持流共享那么其实现必须是透明的。V4L2 API 并没有列出产生冲突时要如何来解决。
1.1.5. 函数(Functions)
应用程序可以使用open()和close()函数来打开、关闭V4L2设备都是雷同的。下面几小节将介绍设备编程所用到的ioctl()方法。
1.2. 功能查询(Querying Capabilities)
因为啊人都想做大嘛这个V4l2 涉及了各式各样的设备但是呢这个API接口却并不能都适合这些个繁杂的设备。因此相同类型的设备就可能拥有完全不一样的能力所以这份规范也允许忽略一些复杂且不那么重要的API接口。
ioctl的VIDIOC_QUERYCAP选项是用来检查内核设备是不是和这份规范相兼容滴也可以顺便看看这些设备所能够支持的函数和I/O方法一举两得。其他的特性嘛也可以依葫芦画瓢调用各自的ioctl方法例子么想知道设备上的视频连接头的名字啊型号和数量神马的就可以调用ioctl的VIDIOC_ENUMINPUT方法.尽管API主要功用是--抽象模糊底层硬件但是ioctl方法是允许驱动特定的应用程序来可靠的辨识相应的驱动的。
但是所有的V4l2驱动都必须支持VIDIOC_QUERYCAP这个方法显而易见的。应用程序都应该在打开设备之后就调用这个方法。
1.3. 应用程序的优先级(Application Priority)
当多个程序共享一个设备时你可能就希望分配给他们不同的优先级想想为什么封建社会的把人分成三六九等虽然不人道但有一方面执政者是希望管理起来方便。不同于传统"rm -rf /"(移除根目录下的一切系统需要内核+文件系统这么做告诉你不存在阻塞)思想视频记录程序可能阻止其他的应用程序使他们失去对视频的控制,不能换电视台(一个劲的放广告这搁谁他也受不鸟啊)。
另一个目的就是允许被用户控制的应用程序对可工作在后台的低优先级的应用进行抢占然后被抢占的在稍后一点的时间重新获得对设备的控制权。
鉴于这些个特性是不可能都在用户空间中实现的V4L2就定义了ioctl的VIDIOC_G_PRIORITY和VIDIOC_S_PRIORITY方法来请求和查询访问文件描述符的优先级。因为有些个驱动并不支持这俩个方法为保持和V4L2的早期版本的兼容性会在打开设备时默认的给他们个中间的优先级。再通过VIDIOC_QUERYCAP后应用程序通常会调用VIDIOC_S_PRIORITY请求一个其他的优先级。
如果ioctls在其他程序拥有更高的优先级时用诸如VIDIOC_S_INPUT方法去改变驱动的属性会返回的错误代码。事件机制如盘的热插拔他会在用户空间中弹出个东东告诉你US13来了会通知应用程序有人在别的地方想篡改属性但是还没添加呢(您老给看看怎么办呗)
1.4. 视频输入/输出(Video Inputs and Outputs)
视频的输入和输出就是设备上的物理连接头。例子是RF红外头复合视频头不知是啥玩意w-Video或者RGB连接头。收音机就没有视频输入、输出了。
如果想去了解可用数量的输入和输出属性应用程序可以分别使用ioctl的VIDIOC_ENUMINPUT和VIDIOC_ENUMOUTPUT方法来枚举来查看。当当前的视频输入被查询的时候Ioctl的VIDIOC_ENUMINPUT方法会返回v4l2_input结构体它包含了可用的信号状态信息。
Ioctl的VIDIOC_G_INPUT和VIDIOC_G_OUTPUT方法会返回当前视频的输入、输出索引。为选择不同的输入、输出应用程序可以使用ioctl的VIDIOC_S_INPUT和VIDOC_S_OUTPUT方法。当设备有一个或多个输入时驱动就必须实现所有的输入类ioctl方法对于输出也是同样的。
Example 1-1. Information about the current video input
struct v4l2_input input;
int index;
if(-1 == ioctl(fd, VIDIOC_G_INPUT, &index)){
perror("VIDIOC_G_INPUT");
exit(EXIT_FAILURE);
}
memset(&input, 0, sizeof(input));
input.index = index;
if(-1 == ioctl(fd, VIDIOC_ENUMINPUT, &input)){
perror("VIDIOC_ENUMINPUT");
exit(EXIT_FAILURE);
}
printf("Current input: %s\n", input.name);
Example 1-2. Switching to the first video input
int index;
index = 0;
if(-1 == ioctl(fd, VIDIOC_S_INPUT, &index)){
perror("VIDIOC_S_INPUT");
exit(EXIT_FAILURE);
}
1.5. 音频输入/输出(Audio Inputs and Outputs)
音频的输入输出也是一个设备的物理连接头。 视频采集设备有输入必须的若有输出就有输出既是0个或多个的意思输出设备有输出这...。无线接收装置是没有音频输入或输出的就是个电磁信号。他们必定拥有一个调频头这也是他们的音频信号来源但是对于本API调频头只是相对于视频的输入、输出的音频设备是没有这些个的。TV卡上的回环接头就是接收音频信号并将它们发到声卡上变成声音却没有被当成音频输出。
音视频的输入输出是有联系的。想想也是视频源通常夹杂音频信号。当视频和音频源是个高频头可参见百科时这就更加明显了。假设存在有两个混合视频输入两个音频输入可以想见会有4种组合状况。视频和音频接头间的关系分别定义在结构体v4l2_input源码在Videodev2.h中和v4l2_output的audioset域中其每一位从零开始都代表着是输入还是输出的索引。
struct v4l2_input{
__u32 index; Identifies the input, set by the application.
__u8 name[32]; Name of the video input, a NUL-terminated ASCII string, for example: "Vin (Composite 2)".
This information is intended for the user, preferably the connector label on the device itself.
__u32 type; /* Type of input */
__u32 audioset; /* Associated audios (bitfield) */
Drivers can enumerate up to 32 video and audio inputs. This field shows which audio inputs were selectable as audio source if this was the currently selected video input. It is a bit mask. The LSB corresponds to audio input 0, the MSB to input 31. Any number of bits can be set, or none.
When the driver does not enumerate audio inputs no bits must be set. Applications shall not interpret this as lack of audio support. Some drivers automatically select audio sources and do not enumerate them since there is no choice anyway.
For details on audio inputs and how to select the current input see Section 1.5.
__u32 tuner; /* Associated tuner */
Capture devices can have zero or more tuners (RF demodulators). When the type is set to V4L2_INPUT_TYPE_TUNER this is an RF connector and this field identifies the tuner. It corresponds to struct v4l2_tuner field index. For details on tuners see Section 1.6.
v4l2_std_id std; Every video input supports one or more different video standards. This field is a set of all supported standards. For details on video standards and how to switch see Section 1.7.
__u32 status; This field provides status information about the input. See Table 3 for flags. Status is only valid when this is the current input.
__u32 reserved[4]; Reserved for future extensions. Drivers must set the array to zero.
};
如果想去知道可用的输入、输出数量和属性应用程序可以分别通过使用ioctl的VIDIOC_ENUMAUDIO和VIDIOC_ENUMAUDOUT方法来枚举他们。当正在使用中的设备被查询时由VIDIOC_ENUMAUDOUT方法返回的v4l2_audio结构中包含了可用的信号状态信息。
struct v4l2_audio{
__u32 index; Identifies the audio input, set by the driver or Application.
__u8 name[32]; Name of the audio input, a NUL-terminated ASCII string, for example: "Line In". This information is intended for the user, preferably the connector label on the device itself.
__u32 capability; Audio capability flags, see Table 2.
__u32 mode; Audio mode flags set by drivers and applications (on VIDIOC_S_AUDIO ioctl), see Table 3.
__u32 reserved[2]; Reserved for future extensions. Drivers and applications must set the array to zero.
};
Ioctl的VIDIOC_G_AUDIO和VIDIOC_G_AUDOUT方法会分别返回当前音频的输入和输出。和VIDIOC_G_INPUT,VIDIOC_G_OUTPUT不同他们不仅仅返回个索引而是类似VIDIOC_ENUMAUDIO和VIDIOC_ENUMDOUT返回的结构体。
意欲选择音频的输入或者是改变其属性应用程序可以调用ioctl的VIDIOC_S_AUDIO方法。同样的如果想选择音频输出要知道他们是没有可变属性的则可以调用VIDIOC_S_AUDOUT方法。
当设备具有一个或多个输入、输出时驱动就必须实现所有相应的ioctl方法如果设备具有任何音频输入或者输出驱动就必须设置由VIDIOC_QUERYCAP方法返回的v4l2_capability结构中V4L2_CAP_AUDIO标志位。
struct v4l2_capability{
__u8 driver[16]; Name of the driver, a unique NUL-terminated ASCII string. For example: "bttv". Driver specific applications can use this information to verify the driver identity.
It is also useful to work around known bugs, or to identify drivers in errorr eports.
The driver version is stored in the version field. Storing strings in fixed sized arrays is bad practice but unavoidable here. Drivers and applications should take precautions to never read or write beyond the end of the array and to make sure the strings are properly NUL-terminated.
__u8 card[32]; Name of the device, a NUL-terminated ASCII string. For example: "Yoyodyne TV/FM". One driver may support different brands or models of video hardware. This information is intended for users, for example in a menu of available devices.
Since multiple TV cards of the same brand may be installed which are supported by the same driver, this name should be combined with the character device file name (e. g. /dev/video2) or the bus_info string to avoid ambiguities.
__u8 bus_info[32]; Location of the device in the system, a NUL-terminated ASCII string. For example: "PCI Slot 4". This information is intended for users, to distinguish multiple identical devices. If no such information is available the field may simply count the devices controlled by the driver, or contain the empty string (bus_info[0] = 0).
__u32 version; Version number of the driver. Together with the driver field this identifies a particular driver.
The version number is formatted using the KERNEL_VERSION() macro:
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) __u32 version = KERNEL_VERSION
__u32 capabilities; Device capabilities, see Table 2.
__u32 reserved[4]; Reserved for future extensions. Drivers must set this array to zero.
};
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
Table 2. Device Capabilities Flags
V4L2_CAP_VIDEO_CAPTURE 0x00000001 The device supports the Video Capture interface.
V4L2_CAP_VIDEO_OUTPUT 0x00000002 The device supports the Video Output interface.
V4L2_CAP_VIDEO_OVERLAY 0x00000004 The device supports the Video Overlay interface.
A video overlay device typically stores captured images directly in the video memory of a graphics card,with hardware clipping and scaling.
V4L2_CAP_VBI_CAPTURE 0x00000010 The device supports the Raw VBI Capture interface, providing Teletext and Closed Caption data.
V4L2_CAP_VBI_OUTPUT 0x00000020 The device supports the Raw VBI Output interface.
V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 The device supports the Sliced VBI Capture interface.
V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 The device supports the Sliced VBI Output interface.
V4L2_CAP_RDS_CAPTURE 0x00000100 [to be defined]
Example 1-3. Information about the current audio input
struct v4l2_audio audio;
memset (&audio, 0, sizeof (audio));
if (-1 == ioctl (fd, VIDIOC_G_AUDIO, &audio)) {
perror ("VIDIOC_G_AUDIO");
exit (EXIT_FAILURE);
}
printf ("Current input: %s\n", audio.name);
Example 1-4. Switching to the first audio input
struct v4l2_audio audio;
memset (&audio, 0, sizeof (audio)); /* clear audio.mode, audio.reserved */
audio.index = 0;
if (-1 == ioctl (fd, VIDIOC_S_AUDIO, &audio)) {
perror ("VIDIOC_S_AUDIO");
exit (EXIT_FAILURE);
}
1.6. 高频头和调制器Tuners and Modulators
1.6.1. 高频头(Tuners)
视频输入设备可能有一个或多个高频头来解调RF射频信号。VIDIOC_ENUMINPUT方法会返回type域被设置成V4L2_INPUT_TYPE_TUNER的v4l2_input结构体且其中的tuner域也包含着tuner的索引号码。
无线发射设备通常只有索引号为0的这么一个tuner同时没有任何视频输入。
应用程序可以分别通过使用VIDIOC_G_TUNER和VIDIOC_S_TUNER方法来查询和改变tuner的属性。当正在使用中的设备被查询时由VIDIOC_G_TUNER方法返回的v4l2_tuner结构中包含了可用的信号状态信息。需要注意的是当拥有多个tuner时VIDIOC_S_TUNER并不会切换当前的tuner。其实这个tuner是由当前的视频输入唯一确定的。当设备含有一个或多个tuner时驱动就必须支持ioctl方法和提供设置由VIDIOC_QUERYCAP返回的v4l2_capability中V4L2_CAP_TUNER标志。
...
#define VIDIOC_G_TUNER _IOWR(‘V’, 29, struct v4l2_tuner)
#define VIDIOC_S_TUNER _IOW(‘V’, 30, struct v4l2_tuner)
...
1.6.2. 调制器Modulators
视频输出设备可以有一个或多个调制器他可以将视频信号调制成TV电线的解说信号或者是视频记录器的。每个调制器是和一个或多个视频输出相关联的而关联的数量取决于RF射频连接头的数量。
VIDIOC_ENUMOUTPUT方法返回的v4l2_output结构中的type域会被设置成V4L2_OUTPUT_TYPE_MODULATOR,而他的modulator域包含了modulator的索引号。规范并没有定义无线输出设备。
struct v4l2_output {
__u32 index; /* Which output */
__u8 name[32]; /* Label */
__u32 type; /* Type of output */
__u32 audioset; /* Associated audios (bitfield) */
__u32 modulator; /* Associated modulator */
v4l2_std_id std;
__u32 reserved[4];
};
应用程序可以使用VIDIOC_G_MODULATOR和VIDIOC_S_MODULATOR方法来查询和改变modulator的属性。需要注意的是当拥有多个tuner时VIDIOC_S_MODULATOR并不会切换当前的modulator。其实这个modulator是由当前的视频输入唯一确定的.当设备含有一个或多个modulator时驱动就必须支持ioctl方法和提供设置由VIDIOC_QUERYCAP返回的v4l2_capability中V4L2_CAP_MODULATOR标志。
1.6.3. 无线频率(Radio Frequency)
struct v4l2_frequency {
__u32 tuner; The tuner or modulator index number. This is the same value as in the struct v4l2_input tuner field and the struct v4l2_tuner index field, or the struct v4l2_output modulator field and the
struct v4l2_modulator index field.
enum v4l2_tuner_type type; The tuner type. This is the same value as in the struct v4l2_tuner type field. The field is not applicable to modulators, i.e.ignored by drivers.
__u32 frequency; Tuning frequency in units of 62.5 kHz, or if the struct v4l2_tuner or struct v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set, in units of 62.5 Hz.
__u32 reserved[8]; Reserved for future extensions. Drivers and applications must set the array to zero.
};
应用程序可以使用VIDIOC_G_FREQUENCY和VIDIOC_S_FREQUENCY方法来获得和设置tuner或者modulator的无线频率。这些个方法同样适用于TV和无线设备。当提供tuner和modulator的ioctl方法时驱动就必须实现相关方法。
1.6.4. 卫星接收器(Satellite Receivers)
将要讨论。可以参见Peter Schlaf的建议位于邮件列表video4linux-list@redhat.com上发表于2002年10月23号主题是"Re: [V4L] Re: v4l2 api"。