4.7. 切片 VBI 数据接口

VBI 代表垂直消隐间隔,是模拟视频信号的行序列中的一个间隙。在 VBI 期间,不传输任何图像信息,从而允许阴极射线管电视的电子束返回到屏幕顶部时有一些时间。

切片 VBI 设备使用硬件来解调在 VBI 中传输的数据。V4L2 驱动程序不应通过软件执行此操作,另请参阅 原始 VBI 接口。数据作为固定大小的短数据包传递,每个数据包覆盖一条扫描线。每个视频帧的数据包数量是可变的。

切片 VBI 捕获和输出设备通过与原始 VBI 设备相同的字符特殊文件进行访问。当驱动程序同时支持这两个接口时,/dev/vbi 设备的默认功能是原始 VBI 捕获或输出,只有在调用如下定义的 VIDIOC_S_FMT ioctl 之后,切片 VBI 功能才可用。同样,/dev/video 设备可能支持切片 VBI API,但此处的默认功能是视频捕获或输出。如果驱动程序支持,则必须使用不同的文件描述符来同时传递原始和切片 VBI 数据。

4.7.1. 查询功能

支持切片 VBI 捕获或输出 API 的设备分别在通过 ioctl VIDIOC_QUERYCAP ioctl 返回的 struct v4l2_capabilitycapabilities 字段中设置 V4L2_CAP_SLICED_VBI_CAPTUREV4L2_CAP_SLICED_VBI_OUTPUT 标志。必须支持至少一种读/写或流式 I/O 方法。切片 VBI 设备可能具有调谐器或调制器。

4.7.2. 补充功能

如果切片 VBI 设备具有这些功能,则它们应支持 视频输入或输出调谐器或调制器 ioctl,并且它们可能支持 用户控件 ioctl。视频标准 ioctl 提供对切片 VBI 设备进行编程至关重要的信息,因此必须支持。

4.7.3. 切片 VBI 格式协商

为了找出硬件支持哪些数据服务,应用程序可以调用 VIDIOC_G_SLICED_VBI_CAP ioctl。所有实现切片 VBI 接口的驱动程序都必须支持此 ioctl。当硬件每个帧可以捕获或输出的 VBI 行数,或者在给定行上可以识别的服务数量受到限制时,结果可能与 VIDIOC_S_FMT ioctl 的结果不同。例如,在 PAL 第 16 行上,硬件可能能够查找 VPS 或图文电视信号,但不能同时查找两者。

为了确定当前选择的服务,应用程序将 struct v4l2_formattype 字段设置为 V4L2_BUF_TYPE_SLICED_VBI_CAPTUREV4L2_BUF_TYPE_SLICED_VBI_OUTPUT,并且 VIDIOC_G_FMT ioctl 填充 fmt.sliced 成员,即 struct v4l2_sliced_vbi_format

应用程序可以通过初始化或修改 fmt.sliced 成员并调用 VIDIOC_S_FMT ioctl 并传递指向 struct v4l2_format 结构的指针来请求不同的参数。

切片 VBI API 比原始 VBI API 更复杂,因为必须告诉硬件在每条扫描线上期望哪个 VBI 服务。并非所有服务都可能在所有行上都受硬件支持(对于图文电视通常不受支持且其他服务只能插入一条特定行的 VBI 输出尤其如此)。但是,在许多情况下,仅将 service_set 字段设置为所需的服务并让驱动程序根据硬件功能填充 service_lines 数组就足够了。只有在需要更精确的控制时,程序员才应显式设置 service_lines 数组。

VIDIOC_S_FMT ioctl 根据硬件功能修改参数。当驱动程序在此处分配资源时,如果所需资源暂时不可用,它可能会返回 EBUSY 错误代码。其他可能返回 EBUSY 的资源分配点可以是 ioctl VIDIOC_STREAMON, VIDIOC_STREAMOFF ioctl 以及首次的 read()write()select() 调用。

type v4l2_sliced_vbi_format

4.7.3.1. struct v4l2_sliced_vbi_format

__u16

service_set

如果在使用 VIDIOC_S_FMTVIDIOC_TRY_FMT 传递时,service_set 为非零,则驱动程序将根据此字段中指定的服务填充 service_lines 数组。例如,如果 service_set 使用 V4L2_SLICED_TELETEXT_B | V4L2_SLICED_WSS_625 初始化,则 cx25840 视频解码器的驱动程序将两个字段 [1] 的第 7-22 行设置为 V4L2_SLICED_TELETEXT_B,并将第一个字段的第 23 行设置为 V4L2_SLICED_WSS_625。如果 service_set 设置为零,则将改为使用 service_lines 的值。

在返回时,驱动程序会将此字段设置为返回的 service_lines 数组的所有元素的并集。如果硬件不能同时处理更多服务,则它可能包含比请求的服务更少,也许只有一个。如果硬件不支持任何请求的服务,则它可能为空(零)。

__u16

service_lines[2][24]

应用程序使用驱动程序应在相应扫描线上查找或插入的数据服务集初始化此数组。根据硬件功能,驱动程序返回请求的集合、子集(可能只是一个服务)或空集。当硬件无法在同一条线上处理多个服务时,驱动程序应选择一个。不能对驱动程序选择哪个服务进行任何假设。

数据服务在 切片 VBI 服务 中定义。数组索引按以下方式映射到 ITU-R 行号[2]

元素

525 行系统

625 行系统

service_lines[0][1]

1

1

service_lines[0][23]

23

23

service_lines[1][1]

264

314

service_lines[1][23]

286

336

驱动程序必须将 service_lines[0][0] 和 service_lines[1][0] 设置为零。V4L2_VBI_ITU_525_F1_STARTV4L2_VBI_ITU_525_F2_STARTV4L2_VBI_ITU_625_F1_STARTV4L2_VBI_ITU_625_F2_START 定义为了方便起见,为每种 525 或 625 行格式的每个字段提供起始行号。不要忘记 ITU 行编号从 1 开始,而不是 0。

__u32

io_size

通过一次 read()write() 调用传递的最大字节数,以及 ioctl VIDIOC_QBUF, VIDIOC_DQBUFVIDIOC_DQBUF ioctl 的缓冲区大小(以字节为单位)。驱动程序将此字段设置为结构体 v4l2_sliced_vbi_data 的大小乘以返回的 service_lines 数组中非零元素的数量(即可能携带数据的行数)。

__u32

保留[2]

此数组保留用于未来的扩展。

应用程序和驱动程序必须将其设置为零。

4.7.3.2. 切片 VBI 服务

符号

参考

行,通常

有效载荷

V4L2_SLICED_TELETEXT_B (图文电视系统 B)

0x0001

ETS 300 706,

ITU BT.653

PAL/SECAM 行 7-22、320-335(第二场 7-22)

45 字节图文电视数据包的最后 42 个字节,即不包括时钟同步和帧定界码,先发送最低有效位。

V4L2_SLICED_VPS

0x0400

ETS 300 231

PAL 行 16

根据 ETS 300 231 的图 9,字节编号 3 到 15,先发送最低有效位。

V4L2_SLICED_CAPTION_525

0x1000

CEA 608-E

NTSC 行 21, 284(第二场 21)

按传输顺序排列的两个字节,包括奇偶校验位,先发送最低有效位。

V4L2_SLICED_WSS_625

0x4000

ITU BT.1119,

EN 300 294

PAL/SECAM 行 23

请参阅下面的 V4L2_SLICED_WSS_625 有效载荷

V4L2_SLICED_VBI_525

0x1000

适用于 525 行系统的服务集。

V4L2_SLICED_VBI_625

0x4401

适用于 625 行系统的服务集。

当应用程序在没有事先协商格式、切换视频标准(可能会使协商的 VBI 参数无效)和切换视频输入(可能会改变视频标准)后尝试读取或写入数据时,驱动程序可能会返回 EINVAL 错误代码。当应用程序在 I/O 正在进行时(在 ioctl VIDIOC_STREAMON, VIDIOC_STREAMOFFVIDIOC_STREAMOFF 调用之间,以及第一次 read()write() 调用之后)尝试更改格式时,VIDIOC_S_FMT ioctl 可能会返回 EBUSY 错误代码。

4.7.3.2.1. V4L2_SLICED_WSS_625 有效载荷

V4L2_SLICED_WSS_625 的有效载荷为

字节

0

1

最高有效位

最低有效位

最高有效位

最低有效位

7

6

5

4

3

2

1

0

x

x

13

12

11

10

9

8

4.7.4. 读取和写入切片 VBI 数据

单个 read()write() 调用必须传递属于一个视频帧的所有数据。也就是说,一个或多个 v4l2_sliced_vbi_data 结构体的数组,总大小不超过 io_size 字节。同样,在流式 I/O 模式下,一个 io_size 字节的缓冲区必须包含一个视频帧的数据。未使用的 v4l2_sliced_vbi_data 结构体的 id 必须为零。

type v4l2_sliced_vbi_data

4.7.4.1. 结构体 v4l2_sliced_vbi_data

__u32

id

来自 切片 VBI 服务 的标志,用于标识此数据包中的数据类型。只能设置一位。当捕获的数据包的 id 为零时,该数据包为空,并且其他字段的内容未定义。应用程序应忽略空数据包。当用于输出的数据包的 id 为零时,data 字段的内容未定义,并且驱动程序不得再在请求的 fieldline 上插入数据。

__u32

field

此数据已从中捕获或将要插入的视频场号。0 表示第一场,1 表示第二场。

__u32

line

此数据已从中捕获或将要插入的场(而不是帧)行号。有关有效值,请参阅 图 4.2. ITU-R 525 行编号 (M/NTSC 和 M/PAL)图 4.3. ITU-R 625 行编号。如果硬件无法可靠地识别扫描线,则切片 VBI 捕获设备可以将所有数据包的行号设置为 0。场号必须始终有效。

__u32

保留

此字段保留用于未来的扩展。应用程序和驱动程序必须将其设置为零。

__u8

data[48]

数据包有效载荷。有关每种数据类型传递的内容和字节数,请参阅 切片 VBI 服务。此数组末尾的填充字节的内容未定义,驱动程序和应用程序应忽略它们。

数据包始终按升序行号传递,没有重复的行号。当应用程序违反此规则时,write() 函数和 ioctl VIDIOC_QBUF, VIDIOC_DQBUF ioctl 必须返回 EINVAL 错误代码。当应用程序传递不正确的场号或行号,或与 VIDIOC_G_FMTVIDIOC_S_FMT ioctl 未协商的 fieldlineid 的组合时,它们也必须返回 EINVAL 错误代码。当行号未知时,驱动程序必须按传输顺序传递数据包。驱动程序可以在数据包数组中的任何位置插入 id 设置为零的空数据包。

为了确保同步并区分帧丢失,当捕获的帧不携带任何请求的数据服务时,驱动程序必须传递一个或多个空数据包。当应用程序未能及时传递 VBI 数据进行输出时,驱动程序必须再次输出上一个 VPS 和 WSS 数据包,并禁用闭路字幕和图文电视数据的输出,或输出闭路字幕和图文电视解码器忽略的数据。

切片 VBI 设备可能支持 读取/写入 和/或流式(内存映射 和/或 用户指针)I/O。后者可以通过使用缓冲区时间戳来实现视频和 VBI 数据的同步。

4.7.5. MPEG 流中的切片 VBI 数据

如果设备可以生成 MPEG 输出流,则它可能能够将 协商的切片 VBI 服务 作为嵌入在 MPEG 流中的数据提供。用户或应用程序使用 V4L2_CID_MPEG_STREAM_VBI_FMT 控制来控制此切片 VBI 数据的插入。

如果驱动程序不提供 V4L2_CID_MPEG_STREAM_VBI_FMT 控制,或仅允许将该控制设置为 V4L2_MPEG_STREAM_VBI_FMT_NONE,则该设备无法将切片 VBI 数据嵌入到 MPEG 流中。

V4L2_CID_MPEG_STREAM_VBI_FMT 控制不会隐式地设置设备驱动程序来捕获或停止捕获切片 VBI 数据。该控制仅指示将切片 VBI 数据嵌入到 MPEG 流中(如果应用程序已协商要捕获的切片 VBI 服务)。

也可能存在一种情况,即设备只能在某些类型的 MPEG 流中嵌入切片 VBI 数据:例如在 MPEG-2 PS 中,但不能在 MPEG-2 TS 中。在这种情况下,如果请求插入切片 VBI 数据,则当支持时,切片 VBI 数据将嵌入到 MPEG 流类型中,并且当设备不支持插入切片 VBI 数据时,将从 MPEG 流类型中静默省略。

以下小节指定嵌入的切片 VBI 数据的格式。

4.7.5.1. MPEG 流嵌入,切片 VBI 数据格式:NONE

驱动程序应将 V4L2_MPEG_STREAM_VBI_FMT_NONE 嵌入式切片 VBI 格式解释为停止在 MPEG 流中嵌入切片 VBI 数据的控制。当设置此格式时,设备和驱动程序都不应在 MPEG 流中插入“空”嵌入式切片 VBI 数据包。此格式未指定 MPEG 流数据结构。

4.7.5.2. MPEG 流嵌入式切片 VBI 数据格式:IVTV

当支持 V4L2_MPEG_STREAM_VBI_FMT_IVTV 嵌入式切片 VBI 格式时,它指示驱动程序在 MPEG 流中,将每个帧最多 36 行的切片 VBI 数据嵌入到 MPEG-2 *私有流 1 PES* 数据包中,该数据包封装在 MPEG-2 *节目包* 中。

历史背景:此格式规范源自 ivtv 驱动程序使用的自定义嵌入式切片 VBI 数据格式。此格式已在内核源代码中的文件 Documentation/userspace-api/media/drivers/cx2341x-uapi.rst 中非正式指定。此格式的最大负载大小和其他方面受 CX23415 MPEG 解码器在提取、解码和显示 MPEG 流中嵌入的切片 VBI 数据方面的能力和限制所驱动。

此格式的使用并非 ivtv 驱动程序独有,也并非 CX2341x 设备独有,因为切片 VBI 数据包插入 MPEG 流是在驱动程序软件中实现的。至少 cx18 驱动程序也以这种格式将切片 VBI 数据插入到 MPEG-2 PS 中。

以下定义指定当设置 V4L2_MPEG_STREAM_VBI_FMT_IVTV 时,包含切片 VBI 数据的 MPEG-2 *私有流 1 PES* 数据包的负载。(此处未详细介绍 MPEG-2 *私有流 1 PES* 数据包头和封装的 MPEG-2 *节目包* 头。有关这些数据包头的详细信息,请参阅 MPEG-2 规范。)

包含切片 VBI 数据的 MPEG-2 *私有流 1 PES* 数据包的负载由结构体 v4l2_mpeg_vbi_fmt_ivtv 指定。负载的长度是可变的,具体取决于视频帧中存在的切片 VBI 数据的实际行数。负载末尾可以使用未指定的填充字节进行填充,以使负载的末尾与 4 字节边界对齐。负载永远不会超过 1552 字节(2 个场,每个场 18 行,每行 43 字节的数据和一个 4 字节的魔数)。

type v4l2_mpeg_vbi_fmt_ivtv

4.7.5.3. 结构体 v4l2_mpeg_vbi_fmt_ivtv

__u8

magic[4]

来自 结构体 v4l2_mpeg_vbi_fmt_ivtv 魔术字段的魔术常量 的一个“魔术”常量,它指示这是一个有效的切片 VBI 数据负载,并且还指示要使用匿名联合 itv0ITV0 中的哪个成员作为负载数据。

union {

(anonymous)

struct v4l2_mpeg_vbi_itv0

itv0

切片 VBI 数据负载的主要形式,其中包含 1 到 35 行的切片 VBI 数据。此负载形式中提供了行掩码,指示提供了哪些 VBI 行。

struct v4l2_mpeg_vbi_ITV0

ITV0

当存在 36 行切片 VBI 数据时,使用的切片 VBI 数据负载的替代形式。此负载形式不提供行掩码;所有有效的行掩码位均被隐式设置。

}

4.7.5.4. 结构体 v4l2_mpeg_vbi_fmt_ivtv 魔术字段的魔术常量

定义的符号

描述

V4L2_MPEG_VBI_IVTV_MAGIC0

“itv0”

指示结构体 v4l2_mpeg_vbi_fmt_ivtv 中的联合成员 itv0 有效。

V4L2_MPEG_VBI_IVTV_MAGIC1

“ITV0”

指示结构体 v4l2_mpeg_vbi_fmt_ivtv 中的联合成员 ITV0 有效,并且存在 36 行切片 VBI 数据。

type v4l2_mpeg_vbi_itv0
type v4l2_mpeg_vbi_ITV0

4.7.5.5. 结构体 v4l2_mpeg_vbi_itv0 和 v4l2_mpeg_vbi_ITV0

__le32

linemask[2]

指示存在的 VBI 服务行的位掩码。这些 linemask 值以小端字节顺序存储在 MPEG 流中。下面给出了一些参考 linemask 位位置及其对应的 VBI 行号和视频场。b0 表示 linemask 值的最低有效位。

linemask[0] b0:     line  6  first field
linemask[0] b17:    line 23  first field
linemask[0] b18:    line  6  second field
linemask[0] b31:    line 19  second field
linemask[1] b0:     line 20  second field
linemask[1] b3:     line 23  second field
linemask[1] b4-b31: unused and set to 0

struct v4l2_mpeg_vbi_itv0_line

line[35]

这是一个可变长度的数组,保存 1 到 35 行的切片 VBI 数据。存在的切片 VBI 数据行与 linemask 数组中设置的位对应,从 linemask[0] 的 b0 开始,直到 linemask[0] 的 b31,以及从 linemask[1] 的 b0 开始,直到 linemask[1] 的 b3line[0] 对应于 linemask 数组中找到的第一个设置位,line[1] 对应于 linemask 数组中找到的第二个设置位,依此类推。如果未设置 linemask 数组位,则 line[0] 可能包含一行未指定的数据,应用程序应忽略该数据。

4.7.5.6. 结构体 v4l2_mpeg_vbi_ITV0

struct v4l2_mpeg_vbi_itv0_line

line[36]

一个固定长度的切片 VBI 数据数组,包含 36 行。line[0] 到 line[17] 对应于第一场的第 6 到 23 行。line[18] 到 line[35] 对应于第二场的第 6 到 23 行。

type v4l2_mpeg_vbi_itv0_line

4.7.5.7. 结构体 v4l2_mpeg_vbi_itv0_line

__u8

id

来自 结构体 v4l2_mpeg_vbi_itv0_line id 字段的行标识符常量 的行标识符值,指示此行上存储的切片 VBI 数据类型。

__u8

data[42]

该行的切片 VBI 数据。

4.7.5.8. 结构体 v4l2_mpeg_vbi_itv0_line id 字段的行标识符

定义的符号

描述

V4L2_MPEG_VBI_IVTV_TELETEXT_B

1

有关行负载的说明,请参阅 切片 VBI 服务

V4L2_MPEG_VBI_IVTV_CAPTION_525

4

有关行负载的说明,请参阅 切片 VBI 服务

V4L2_MPEG_VBI_IVTV_WSS_625

5

有关行负载的说明,请参阅 切片 VBI 服务

V4L2_MPEG_VBI_IVTV_VPS

7

有关行负载的说明,请参阅 切片 VBI 服务