官方文档地址:http://v4l2spec.bytesex.org/
$Chapter 1. Common API Elements
V4L2设备编程包含如下步骤:
1.打开设备
2.改变设备属性,选择一个video和audio输入、video标准、图片亮度等等
3.确定一个数据格式
4.确定一个输入输出方法;
5.实际的输入输出环(input/output loop)
6.关闭设备
在实际应用中,有些步骤可能是不需要的,或者无序的。
*1.1 关闭和打开设备
**1.1.1 设备名
#视频设备驱动,可能注册一个或多个设备节点。这些设备节点的主设备号是81,次设备号在0-255之间。
#一般用次设备号0和1,注册头两个视频捕获设备;
而用次设备号64和65,注册头两个radio设备。
**1.1.2 相关设备
#设备可以支持相关的功能:
video capturing, video overlay、 VBI capturing(/dev/vbi,Major:81,Minor224)、FM radio
/dev/video捕获视频图像;/dev/vbi捕获 raw VBI数据。
/dev/radio(81,64)在radio设备中是不变的,与video功能无关。
**1.1.3 同时打开(Multiple Opens)
#当一个应用程序在捕获视频和audio的同时,另一个应用程序可以改变亮度或声音。
Multiple opens应该允许并发使用设备。
应用程序使用优先级机制可以获得特权访问(Section 1.3)。
1.1.4 共享数据流(Shared Data Streams)
#V4L2 驱动应该不支持多应用程序同时通过拷贝buffers来读写同一个设备上的同一个数据流(data stream);
当驱动支持数据流共享,那么它必须被透明地实现。
*1.2 查询功能(Querying Capabilities)
#ioctl 的这个 “VIDIOC_QUERYCAP” 就是用来查询驱动支持哪些功能。所有的V4L2驱动必须支持“VIDIOC_QUERYCAP”,并且应用程序每次打开设备之后必须调用这个“VIDIOC_QUERYCAP”的ioctl。
*1.3 应用优先级(Application Priority)
#当多个应用程序共享一个设备时,那么就需要给他们分配不同的优先级。
#V4L2定义了“VIDIOC_G_PRIORITY”和“VIDIOC_S_PRIORITY”,分别用来查询和设置(s代表set,g代表get)访问的优先级(每个应用程序对应一个文件描述符)。
在使用“VIDIOC_QUERYCAP”验证了功能之后,应用程序再通过“VIDIOC_S_PRIORITY”请求一个优先级。
#在另一个应用程序获得了更高的优先级之后,一个应用程序改变驱动属性的操作如“VIDIOC_S_INPUT”,会返回一个EBUSY的错误。当然,有一个事件机制可以告诉这个应用程序,异步属性改变,可以添加了(但是你之前没有添加成功)。
*1.4. 视频输入输出(Video Inputs and Outputs)
#视频输入和输出是利用设备的物理连接器(天线、CVBS、S-Video和RGB接口等)来进行的。
#仅video和VBI捕获(capture)设备具有输入、输出设备,而Radio设备没有video输入和输出。
#要知道有效的输入输出的属性和数量,应用程序通过“VIDIOC_ENUMINPUT”和“VIDIOC_ENUMOUTPUT”可以枚举这些属性。
##相应的,struct v4l2_input 里的值,是由 ioctl(,VIDIOC_ENUMINPUT,&a_v4l2_input)来设置的。
struct v4l2_input 里获得的值,包含了设备的信号状态信息,在当前video input 被查询的时候。
##“VIDIOC_G_INPUT”的ioctl,返回一个当前video input或output的索引(index)。
可以通过“VIDIOC_S_INPUT”和“VIDIOC_S_OUTPUT”两个ioctl来选择不同的输入或输出应用程序。
#当设备具有1个或多个输入(1个或多个输出)时,驱动必须实现所有的 “输入ioctl”(输入ioctl)。
示例1-1. 当前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;//设置input中的索引
if (-1 == ioctl (fd, VIDIOC_ENUMINPUT, &input)) {//通过索引,查询枚举input,获得当前input的信息
perror ("VIDIOC_ENUMINPUT");
exit (EXIT_FAILURE);
}
printf ("Current input: %s\n", input.name);//打印获取到的名字。
示例1-2.切换到第一个video input
int index;
index = 0;//而对应的VIDIOC_G_INPUT的操作返回了index;
if (-1 == ioctl (fd, VIDIOC_S_INPUT, &index)) {//索引0对应了第一个video input;通过VIDIOC_S_INPUT根据index的值把当前设置成第一个video input
perror ("VIDIOC_S_INPUT");
exit (EXIT_FAILURE);
}
*1.5. 音频输入和输出(Audio Inputs and Outputs)
#Radio设备米有audio input或output。他们实际上是一个频道,这个频道实际上是一个audio source(音频源)。
一个TV卡的连接器轮回接受audio信号,并把信号送至声卡,那么这个TV卡上的连接器不被认为是一个audio output。
#audio和video输入输出是由关联的。假定2路符合视频输入和2路audio输