6.1. V4L 和 V4L2 之间的差异

Video For Linux API 最早于 Linux 2.1 中引入,旨在统一和取代驱动开发者在前几年独立开发的各种电视和无线电设备相关接口。从 Linux 2.5 开始,大幅改进的 V4L2 API 取代了 V4L API。对旧 V4L 调用的支持已从内核中移除,但库 Libv4l 用户空间库 支持将 V4L API 系统调用转换为 V4L2 调用。

6.1.1. 打开和关闭设备

出于兼容性考虑,推荐用于 V4L2 视频捕获、覆盖、无线电和原始 VBI 捕获设备的字符设备文件名与 V4L 使用的文件名保持不变。它们列在 接口 中,并在下文的 V4L 设备类型、名称和编号 中。

图文电视设备(次设备号范围 192-223)已在 V4L2 中移除,不再存在。目前没有可用的硬件来处理纯图文电视。取而代之的是使用原始或切片 VBI。

V4L videodev 模块根据注册的设备类型,自动按加载顺序为驱动程序分配次设备号。我们建议 V4L2 驱动程序默认注册具有相同编号的设备,但系统管理员可以使用驱动程序模块选项分配任意次设备号。主设备号保持为 81。

V4L 设备类型、名称和编号

设备类型

文件名

次设备号

视频捕获和覆盖

/dev/video/dev/bttv0 [1], /dev/video0/dev/video63

0-63

无线电接收器

/dev/radio [2], /dev/radio0/dev/radio63

64-127

原始 VBI 捕获

/dev/vbi, /dev/vbi0/dev/vbi31

224-255

V4L 禁止(或曾经禁止)多次打开设备文件。V4L2 驱动程序可能支持多次打开,详情和后果请参阅 打开和关闭设备

V4L 驱动程序对 V4L2 ioctl 的响应是返回 EINVAL 错误代码。

6.1.2. 查询功能

V4L 的 VIDIOCGCAP ioctl 等同于 V4L2 的 ioctl VIDIOC_QUERYCAP

struct video_capability 中的 name 字段在 struct v4l2_capability 中变成了 cardtypecapabilities 取代。请注意,V4L2 不再像这样区分设备类型,最好将其视为支持视频捕获、视频覆盖和 VBI 捕获等相关功能集的基本视频输入、视频输出和无线电设备。有关介绍,请参阅 打开和关闭设备

struct video_capability type

struct v4l2_capability capabilities 标志

目的

VID_TYPE_CAPTURE

V4L2_CAP_VIDEO_CAPTURE

支持 视频捕获 接口。

VID_TYPE_TUNER

V4L2_CAP_TUNER

该设备具有 调谐器或调制器

VID_TYPE_TELETEXT

V4L2_CAP_VBI_CAPTURE

支持 原始 VBI 捕获 接口。

VID_TYPE_OVERLAY

V4L2_CAP_VIDEO_OVERLAY

支持 视频覆盖 接口。

VID_TYPE_CHROMAKEY

struct v4l2_framebuffercapability 字段中的 V4L2_FBUF_CAP_CHROMAKEY

是否支持色键覆盖。有关覆盖的更多信息,请参阅 视频覆盖接口

VID_TYPE_CLIPPING

struct v4l2_framebuffercapability 字段中的 V4L2_FBUF_CAP_LIST_CLIPPINGV4L2_FBUF_CAP_BITMAP_CLIPPING

是否支持裁剪覆盖图像,请参阅 视频覆盖接口

VID_TYPE_FRAMERAM

struct v4l2_framebuffercapability 字段中未设置 V4L2_FBUF_CAP_EXTERNOVERLAY

覆盖是否会覆盖帧缓冲区内存,请参阅 视频覆盖接口

VID_TYPE_SCALES

-

此标志指示硬件是否可以缩放图像。V4L2 API 通过使用 VIDIOC_S_CROPVIDIOC_S_FMT ioctl 分别设置裁剪尺寸和图像大小来表示缩放因子。驱动程序返回最接近的可能尺寸。有关裁剪和缩放的更多信息,请参阅 图像裁剪、插入和缩放 -- CROP API

VID_TYPE_MONOCHROME

-

应用程序可以使用 ioctl VIDIOC_ENUM_FMT ioctl 枚举支持的图像格式,以确定设备是否仅支持灰度捕获。有关图像格式的更多信息,请参阅 图像格式

VID_TYPE_SUBCAPTURE

-

应用程序可以调用 VIDIOC_G_CROP ioctl 来确定设备是否支持捕获完整图片的一部分(V4L2 中的“裁剪”)。如果不支持,ioctl 将返回 EINVAL 错误代码。有关裁剪和缩放的更多信息,请参阅 图像裁剪、插入和缩放 -- CROP API

VID_TYPE_MPEG_DECODER

-

应用程序可以使用 ioctl VIDIOC_ENUM_FMT ioctl 枚举支持的图像格式,以确定设备是否支持 MPEG 流。

VID_TYPE_MPEG_ENCODER

-

参见上文。

VID_TYPE_MJPEG_DECODER

-

参见上文。

VID_TYPE_MJPEG_ENCODER

-

参见上文。

audios 字段被 capabilities 标志 V4L2_CAP_AUDIO 取代,表示设备是否有任何音频输入或输出。要确定它们的数量,应用程序可以使用 VIDIOC_G_AUDIO ioctl 枚举音频输入。音频 ioctl 在 音频输入和输出 中描述。

maxwidthmaxheightminwidthminheight 字段已被移除。调用 VIDIOC_S_FMTVIDIOC_TRY_FMT ioctl 并指定所需尺寸将返回最接近的可能尺寸,同时考虑到当前视频标准、裁剪和缩放限制。

6.1.3. 视频源

V4L 提供 VIDIOCGCHANVIDIOCSCHAN ioctl,使用 struct video_channel 枚举 V4L 设备的视频输入。等效的 V4L2 ioctl 是 ioctl VIDIOC_ENUMINPUTVIDIOC_G_INPUTVIDIOC_S_INPUT,它们使用 struct v4l2_input,如 视频输入和输出 中所讨论。

计数输入的 channel 字段被重命名为 index,视频输入类型重命名如下:

struct video_channel type

struct v4l2_input type

VIDEO_TYPE_TV

V4L2_INPUT_TYPE_TUNER

VIDEO_TYPE_CAMERA

V4L2_INPUT_TYPE_CAMERA

与表示此输入调谐器数量的 tuners 字段不同,V4L2 假定每个视频输入最多连接到一个调谐器。但是,一个调谐器可以有多个输入,即射频连接器,并且一个设备可以有多个调谐器。与输入关联的调谐器(如果有)的索引号存储在 struct v4l2_inputtuner 字段中。调谐器的枚举在 调谐器和调制器 中讨论。

冗余的 VIDEO_VC_TUNER 标志已被删除。与调谐器关联的视频输入类型为 V4L2_INPUT_TYPE_TUNERVIDEO_VC_AUDIO 标志被 audioset 字段取代。V4L2 考虑具有多达 32 个音频输入的设备。audioset 字段中的每个设置位表示此视频输入组合的一个音频输入。有关音频输入以及如何在其间切换的信息,请参阅 音频输入和输出

描述支持的视频标准的 norm 字段被 std 取代。V4L 规范提到了一个标志 VIDEO_VC_NORM,指示标准是否可以更改。此标志是与 norm 字段一起的后期添加,但在此期间已被移除。V4L2 对视频标准有类似但更全面的方法,有关更多信息,请参阅 视频标准

6.1.4. 调谐

V4L VIDIOCGTUNERVIDIOCSTUNER ioctl 以及 struct video_tuner 可用于枚举 V4L 电视或无线电设备的调谐器。等效的 V4L2 ioctl 是 VIDIOC_G_TUNERVIDIOC_S_TUNER,它们使用 struct v4l2_tuner。调谐器在 调谐器和调制器 中介绍。

计数调谐器的 tuner 字段被重命名为 indexnamerangelowrangehigh 字段保持不变。

指示支持的视频标准的 VIDEO_TUNER_PALVIDEO_TUNER_NTSCVIDEO_TUNER_SECAM 标志已删除。此信息现在包含在关联的 struct v4l2_input 中。目前没有替代 VIDEO_TUNER_NORM 标志来指示视频标准是否可以切换。用于选择不同视频标准的 mode 字段已被 视频标准 中描述的一整套新 ioctl 和结构取代。由于其普遍性,应提及 BTTV 驱动程序除了常规的 VIDEO_MODE_PAL (0)、VIDEO_MODE_NTSCVIDEO_MODE_SECAMVIDEO_MODE_AUTO (3) 之外,还支持多种标准,即 N/PAL Argentina、M/PAL、N/PAL 和 NTSC Japan,编号为 3-6(原文如此)。

指示立体声接收的 VIDEO_TUNER_STEREO_ON 标志在 rxsubchans 字段中变为 V4L2_TUNER_SUB_STEREO。此字段还允许检测单声道和双语音频,详情请参阅 struct v4l2_tuner 的定义。目前没有替代 VIDEO_TUNER_RDS_ONVIDEO_TUNER_MBS_ON 标志。

VIDEO_TUNER_LOW 标志在 struct v4l2_tunercapability 字段中被重命名为 V4L2_TUNER_CAP_LOW

用于更改调谐器频率的 VIDIOCGFREQVIDIOCSFREQ ioctl 被重命名为 VIDIOC_G_FREQUENCYVIDIOC_S_FREQUENCY。它们接受指向 struct v4l2_frequency 的指针,而不是无符号长整型。

6.1.5. 图像属性

V4L2 没有 VIDIOCGPICTVIDIOCSPICT ioctl 以及 struct video_picture 的等效项。以下字段已被 V4L2 控件取代,可通过 ioctls VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENUVIDIOC_G_CTRLVIDIOC_S_CTRL ioctl 访问:

struct video_picture

V4L2 控制 ID

亮度

V4L2_CID_BRIGHTNESS

色调

V4L2_CID_HUE

色彩

V4L2_CID_SATURATION

对比度

V4L2_CID_CONTRAST

白平衡

V4L2_CID_WHITENESS

V4L 图像控件的范围假定为 0 到 65535,没有特定的重置值。V4L2 API 允许任意限制和默认值,这些值可以通过 ioctls VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENU ioctl 进行查询。有关控件的一般信息,请参阅 用户控件

视频图像的 depth(每像素平均位数)由所选图像格式决定。V4L2 不会明确提供此类信息,因为它假定识别该格式的应用程序会知道图像深度,而其他应用程序则无需了解。 palette 字段已移至 struct v4l2_pix_format

struct video_picture palette

struct v4l2_pix_format pixfmt

VIDEO_PALETTE_GREY

V4L2_PIX_FMT_GREY

VIDEO_PALETTE_HI240

V4L2_PIX_FMT_HI240 [3]

VIDEO_PALETTE_RGB565

V4L2_PIX_FMT_RGB565

VIDEO_PALETTE_RGB555

V4L2_PIX_FMT_RGB555

VIDEO_PALETTE_RGB24

V4L2_PIX_FMT_BGR24

VIDEO_PALETTE_RGB32

V4L2_PIX_FMT_BGR32 [4]

VIDEO_PALETTE_YUV422

V4L2_PIX_FMT_YUYV

VIDEO_PALETTE_YUYV [5]

V4L2_PIX_FMT_YUYV

VIDEO_PALETTE_UYVY

V4L2_PIX_FMT_UYVY

VIDEO_PALETTE_YUV420

VIDEO_PALETTE_YUV411

V4L2_PIX_FMT_Y41P [6]

VIDEO_PALETTE_RAW

[7]

VIDEO_PALETTE_YUV422P

V4L2_PIX_FMT_YUV422P

VIDEO_PALETTE_YUV411P

V4L2_PIX_FMT_YUV411P [8]

VIDEO_PALETTE_YUV420P

V4L2_PIX_FMT_YVU420

VIDEO_PALETTE_YUV410P

V4L2_PIX_FMT_YVU410

V4L2 图像格式在 图像格式 中定义。图像格式可以使用 VIDIOC_S_FMT ioctl 选择。

6.1.6. 音频

VIDIOCGAUDIOVIDIOCSAUDIO ioctl 以及 struct video_audio 用于枚举 V4L 设备的音频输入。等效的 V4L2 ioctl 是 VIDIOC_G_AUDIOVIDIOC_S_AUDIO,它们使用 struct v4l2_audio,如 音频输入和输出 中所讨论。

计数音频输入的 audio “通道号”字段被重命名为 index

VIDIOCSAUDIO 上,mode 字段选择 VIDEO_SOUND_MONOVIDEO_SOUND_STEREOVIDEO_SOUND_LANG1VIDEO_SOUND_LANG2 音频解调模式中的一种。当当前音频标准是 BTSC 时,VIDEO_SOUND_LANG2 指的是 SAP,而 VIDEO_SOUND_LANG1 则毫无意义。V4L 规范中也未记录,无法查询所选模式。在 VIDIOCGAUDIO 上,驱动程序在此字段中返回实际接收到的音频节目。在 V4L2 API 中,此信息分别存储在 struct v4l2_tunerrxsubchansaudmode 字段中。有关调谐器的更多信息,请参阅 调谐器和调制器。与音频模式相关,struct v4l2_audio 还报告这是否是单声道或立体声输入,无论来源是否是调谐器。

以下字段已被 V4L2 控件取代,可通过 ioctls VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENUVIDIOC_G_CTRLVIDIOC_S_CTRL ioctl 访问:

struct video_audio

V4L2 控制 ID

音量

V4L2_CID_AUDIO_VOLUME

低音

V4L2_CID_AUDIO_BASS

高音

V4L2_CID_AUDIO_TREBLE

平衡

V4L2_CID_AUDIO_BALANCE

为了确定驱动程序支持哪些控件,V4L 提供了 flags VIDEO_AUDIO_VOLUMEVIDEO_AUDIO_BASSVIDEO_AUDIO_TREBLEVIDEO_AUDIO_BALANCE。在 V4L2 API 中,ioctls VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENU ioctl 报告是否支持相应的控件。因此,VIDEO_AUDIO_MUTABLEVIDEO_AUDIO_MUTE 标志被布尔型 V4L2_CID_AUDIO_MUTE 控件取代。

所有 V4L2 控件都有一个 step 属性,取代了 struct video_audiostep 字段。V4L 音频控件的范围假定为 0 到 65535,没有特定的重置值。V4L2 API 允许任意限制和默认值,这些值可以通过 ioctls VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL 和 VIDIOC_QUERYMENU ioctl 进行查询。有关控件的一般信息,请参阅 用户控件

6.1.7. 帧缓冲区覆盖

VIDIOCGFBUFVIDIOCSFBUF 等效的 V4L2 ioctl 是 VIDIOC_G_FBUFVIDIOC_S_FBUF。struct video_bufferbase 字段保持不变,只是 V4L2 定义了一个标志来指示非破坏性覆盖,而不是 NULL 指针。所有其他字段都移至 struct v4l2_framebuffer 的 struct v4l2_pix_format fmt 子结构中。depth 字段被 pixelformat 取代。有关 RGB 格式及其各自颜色深度的列表,请参阅 RGB 格式

V4L2 不使用特殊的 ioctl VIDIOCGWINVIDIOCSWIN,而是使用通用数据格式协商 ioctl VIDIOC_G_FMTVIDIOC_S_FMT。它们接受指向 struct v4l2_format 的指针作为参数。此处使用的是 fmt 联合体的 win 成员,即 struct v4l2_window

struct video_windowxywidthheight 字段已移至 struct v4l2_window 的 struct v4l2_rect 子结构 w 中。chromakeyclipsclipcount 字段保持不变。struct video_clip 被重命名为 struct v4l2_clip,它也包含一个 struct v4l2_rect,但其语义仍然相同。

VIDEO_WINDOW_INTERLACE 标志已删除。取而代之的是,应用程序必须将 field 字段设置为 V4L2_FIELD_ANYV4L2_FIELD_INTERLACEDVIDEO_WINDOW_CHROMAKEY 标志已移至 struct v4l2_framebuffer 中,并以新名称 V4L2_FBUF_FLAG_CHROMAKEY 存在。

在 V4L 中,将位图指针存储在 clips 中并将 clipcount 设置为 VIDEO_CLIP_BITMAP (-1) 会请求位图裁剪,使用固定大小为 1024 × 625 位的位图。Struct v4l2_window 为此目的有一个单独的 bitmap 指针字段,位图大小由 w.widthw.height 决定。

启用或禁用覆盖的 VIDIOCCAPTURE ioctl 已重命名为 ioctl VIDIOC_OVERLAY

6.1.8. 裁剪

为了仅捕获完整图片的一部分,V4L 定义了使用 struct video_captureVIDIOCGCAPTUREVIDIOCSCAPTURE ioctl。等效的 V4L2 ioctl 是 VIDIOC_G_CROPVIDIOC_S_CROP,它们使用 struct v4l2_crop,以及相关的 ioctl VIDIOC_CROPCAP ioctl。这是一个相当复杂的问题,详情请参阅 图像裁剪、插入和缩放 -- CROP API

struct v4l2_cropxywidthheight 字段已移至 struct v4l2_rect 子结构 c 中。decimation 字段已删除。在 V4L2 API 中,缩放因子由裁剪矩形的大小以及捕获或覆盖图像的大小隐式决定。

用于分别仅捕获奇数或偶数场的 VIDEO_CAPTURE_ODDVIDEO_CAPTURE_EVEN 标志已替换为 struct v4l2_pix_format 和 struct v4l2_window 中名为 field 的字段中的 V4L2_FIELD_TOPV4L2_FIELD_BOTTOM。这些结构用于使用 VIDIOC_S_FMT ioctl 选择捕获或覆盖格式。

6.1.9. 读取图像,内存映射

6.1.9.1. 使用读方法捕获

使用 read() 函数从 V4L 或 V4L2 设备读取图像之间没有本质区别,但 V4L2 驱动程序不要求支持此 I/O 方法。应用程序可以通过 ioctl VIDIOC_QUERYCAP ioctl 确定该函数是否可用。所有与应用程序交换数据的 V4L2 设备都必须支持 select()poll() 函数。

为了选择图像格式和大小,V4L 提供了 VIDIOCSPICTVIDIOCSWIN ioctl。V4L2 使用通用数据格式协商 ioctl VIDIOC_G_FMTVIDIOC_S_FMT。它们接受指向 struct v4l2_format 的指针作为参数,此处使用的是其 fmt 联合体中名为 pix 的 struct v4l2_pix_format

有关 V4L2 读接口的更多信息,请参阅 读/写

6.1.9.2. 使用内存映射捕获

应用程序可以通过将设备内存中的缓冲区(或更常见的是仅将分配在支持 DMA 的系统内存中的缓冲区)映射到其地址空间来从 V4L 设备读取数据。这避免了读方法的数据复制开销。V4L2 也支持内存映射,但有一些不同。

V4L

V4L2

必须在分配缓冲区之前选择图像格式,使用 VIDIOC_S_FMT ioctl。如果没有选择格式,驱动程序可能会使用上一个(可能由另一个应用程序请求的)格式。

应用程序无法更改缓冲区数量。它内置在驱动程序中,除非它有一个模块选项可以在驱动程序模块加载时更改数量。

ioctl VIDIOC_REQBUFS ioctl 分配所需数量的缓冲区,这是初始化序列中的一个必需步骤。

驱动程序将所有缓冲区映射为一块连续的内存区域。VIDIOCGMBUF ioctl 可用于查询缓冲区数量、每个缓冲区相对于虚拟文件起始处的偏移量以及使用的总内存量,这些信息可用作 mmap() 函数的参数。

缓冲区是单独映射的。每个缓冲区的偏移量和大小可以使用 ioctl VIDIOC_QUERYBUF ioctl 确定。

VIDIOCMCAPTURE ioctl 准备一个缓冲区用于捕获。它还确定此缓冲区的图像格式。如果未检测到视频信号,ioctl 会立即返回,最终返回 EAGAIN 错误代码。当驱动程序支持多个缓冲区时,应用程序可以多次调用 ioctl,从而有多个未完成的捕获请求。

VIDIOCSYNC ioctl 暂停执行,直到某个特定缓冲区被填充。

驱动程序维护一个输入队列和一个输出队列。ioctl VIDIOC_QBUF, VIDIOC_DQBUF 将任何空缓冲区入队到输入队列。已填充的缓冲区使用 VIDIOC_DQBUF ioctl 从输出队列中出队。要等待填充的缓冲区可用,可以使用此函数、select()poll()。在将一个或多个缓冲区入队后,必须调用一次 ioctl VIDIOC_STREAMON, VIDIOC_STREAMOFF ioctl 以开始捕获。其对应项 VIDIOC_STREAMOFF 停止捕获并从两个队列中取出所有缓冲区。应用程序可以通过 ioctl VIDIOC_ENUMINPUT ioctl 查询信号状态(如果已知)。

有关内存映射和示例的更深入讨论,请参阅 流 I/O (内存映射)

6.1.10. 读取原始 VBI 数据

最初 V4L API 没有指定原始 VBI 捕获接口,仅将设备文件 /dev/vbi 保留用于此目的。唯一支持此接口的驱动程序是 BTTV 驱动程序,实际上它定义了 V4L VBI 接口。从设备读取会得到一个具有以下参数的原始 VBI 图像:

struct v4l2_vbi_format

V4L, BTTV 驱动程序

采样率

28636363 Hz NTSC(或任何其他 525 行标准);35468950 Hz PAL 和 SECAM(625 行标准)

偏移量

?

每行样本数

2048

样本格式

V4L2_PIX_FMT_GREY。最后四个字节(一个机器字节序整数)包含一个帧计数器。

起始[]

10, 273 NTSC; 22, 335 PAL 和 SECAM

计数[]

16, 16 [9]

标志

0

V4L 规范中未记录,在 Linux 2.3 中,增加了使用 struct vbi_formatVIDIOCGVBIFMTVIDIOCSVBIFMT ioctl 来确定 VBI 图像参数。这些 ioctl 仅与 原始 VBI 数据接口 中指定的 V4L2 VBI 接口部分兼容。

不存在 offset 字段,sample_format 应该是 VIDEO_PALETTE_RAW,等同于 V4L2_PIX_FMT_GREY。其余字段可能与 struct v4l2_vbi_format 等效。

显然,只有 Zoran (ZR 36120) 驱动程序实现了这些 ioctl。其语义与 V4L2 中指定的语义有两种不同之处。参数在 open() 时重置,并且如果参数无效,VIDIOCSVBIFMT 总是返回 EINVAL 错误代码。

6.1.11. 杂项

V4L2 没有 VIDIOCGUNIT ioctl 的等效项。应用程序可以通过重新打开设备并请求 VBI 数据来查找与视频捕获设备关联的 VBI 设备(反之亦然)。详情请参阅 打开和关闭设备

目前没有替代 VIDIOCKEY 和用于微码编程的 V4L 函数的方案。MPEG 压缩和播放设备的新接口已在 扩展控件 API 中记录。