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 的设备分别在v4l2_capability结构体的capabilities字段中设置V4L2_CAP_SLICED_VBI_CAPTUREV4L2_CAP_SLICED_VBI_OUTPUT标志,该结构体由ioctl VIDIOC_QUERYCAP ioctl 返回。必须支持至少一种读取/写入或流式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 或 Teletext 信号,但不能同时查找两者。

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

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

切片 VBI API 比原始 VBI API 更复杂,因为必须告诉硬件期望在每条扫描线上使用哪种 VBI 服务。并非所有服务都可能受到硬件在所有行上的支持(对于 VBI 输出尤其如此,其中 Teletext 通常不受支持,而其他服务只能插入到一条特定行中)。但是,在许多情况下,只需将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. 结构体 v4l2_sliced_vbi_format

__u16

service_set

如果在通过VIDIOC_S_FMTVIDIOC_TRY_FMTservice_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

reserved[2]

此数组保留供将来扩展使用。

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

4.7.3.2. 切片 VBI 服务

符号

参考

通常的行

有效负载

V4L2_SLICED_TELETEXT_B(Teletext 系统 B)

0x0001

ETS 300 706,

ITU BT.653

PAL/SECAM 行 7-22, 320-335(第二个字段 7-22)

45 字节 Teletext 数据包的最后 42 个字节,即没有时钟预热和成帧代码,先传输 lsb。

V4L2_SLICED_VPS

0x0400

ETS 300 231

PAL 第 16 行

ETS 300 231 图 9 中的字节编号 3 到 15,先传输 lsb。

V4L2_SLICED_CAPTION_525

0x1000

CEA 608-E

NTSC 第 21, 284 行(第二个字段 21)

按传输顺序的两个字节,包括奇偶校验位,先传输 lsb。

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

msb

lsb

msb

lsb

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

reserved

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

__u8

data[48]

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

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

为了确保同步并与丢帧区分开来,当捕获的帧不携带任何请求的数据服务时,驱动程序必须传递一个或多个空数据包。当应用程序未能及时传递 VBI 数据以进行输出时,驱动程序必须再次输出上一个 VPS 和 WSS 数据包,并禁用 Closed Caption 和 Teletext 数据的输出,或者输出 Closed Caption 和 Teletext 解码器忽略的数据。

切片 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 服务。

也可能存在设备只能将切片 VBI 数据嵌入某些类型的 MPEG 流中的情况:例如 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 格式解释为停止将切片 VBI 数据嵌入 MPEG 流的控制。设置此格式后,设备和驱动程序都不会在 MPEG 流中插入“空”嵌入式切片 VBI 数据包。未为此格式指定任何 MPEG 流数据结构。

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

当支持V4L2_MPEG_STREAM_VBI_FMT_IVTV嵌入式切片 VBI 格式时,它指示驱动程序在 MPEG 流的 MPEG-2 Program Pack 中封装的 MPEG-2 Private Stream 1 PES 数据包中嵌入每个帧最多 36 行切片 VBI 数据。

历史背景:此格式规范源自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 Private Stream 1 PES 数据包的有效负载。(此处未详细说明 MPEG-2 Private Stream 1 PES 数据包头和封装的 MPEG-2 Program Pack 头。有关这些数据包头的详细信息,请参阅 MPEG-2 规范。)

包含切片 VBI 数据的 MPEG-2 Private Stream 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 magic 字段的幻数的“幻数”常量,指示这是一个有效的切片 VBI 数据有效负载,并且还指示要用于有效负载数据的匿名联合的哪个成员,itv0ITV0

union {

(anonymous)

结构体v4l2_mpeg_vbi_itv0

itv0

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

结构体v4l2_mpeg_vbi_ITV0

ITV0

当存在 36 行切片 VBI 数据时使用的切片 VBI 数据有效负载的另一种形式。有效负载的这种形式不提供行掩码;隐式设置所有有效的行掩码位。

}

4.7.5.4. 结构体 v4l2_mpeg_vbi_fmt_ivtv magic 字段的幻数

已定义符号

描述

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 数据。

类型 v4l2_mpeg_vbi_itv0
类型 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

结构体 v4l2_mpeg_vbi_itv0_line

line[35]

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

4.7.5.6. 结构体 v4l2_mpeg_vbi_ITV0

结构体 v4l2_mpeg_vbi_itv0_line

line[36]

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

类型 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 服务