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_capability
的 capabilities
字段中设置 V4L2_CAP_SLICED_VBI_CAPTURE
或 V4L2_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_format
的 type
字段设置为 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
或 V4L2_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 |
|
如果在使用 VIDIOC_S_FMT 或 VIDIOC_TRY_FMT 传递时, 在返回时,驱动程序会将此字段设置为返回的 |
||
__u16 |
|
应用程序使用驱动程序应在相应扫描线上查找或插入的数据服务集初始化此数组。根据硬件功能,驱动程序返回请求的集合、子集(可能只是一个服务)或空集。当硬件无法在同一条线上处理多个服务时,驱动程序应选择一个。不能对驱动程序选择哪个服务进行任何假设。 |
||
元素 |
525 行系统 |
625 行系统 |
||
|
1 |
1 |
||
|
23 |
23 |
||
|
264 |
314 |
||
|
286 |
336 |
||
驱动程序必须将 |
||||
__u32 |
|
通过一次 |
||
__u32 |
|
此数组保留用于未来的扩展。 应用程序和驱动程序必须将其设置为零。 |
4.7.3.2. 切片 VBI 服务¶
符号 |
值 |
参考 |
行,通常 |
有效载荷 |
---|---|---|---|---|
|
0x0001 |
PAL/SECAM 行 7-22、320-335(第二场 7-22) |
45 字节图文电视数据包的最后 42 个字节,即不包括时钟同步和帧定界码,先发送最低有效位。 |
|
|
0x0400 |
PAL 行 16 |
根据 ETS 300 231 的图 9,字节编号 3 到 15,先发送最低有效位。 |
|
|
0x1000 |
NTSC 行 21, 284(第二场 21) |
按传输顺序排列的两个字节,包括奇偶校验位,先发送最低有效位。 |
|
|
0x4000 |
PAL/SECAM 行 23 |
请参阅下面的 V4L2_SLICED_WSS_625 有效载荷。 |
|
|
0x1000 |
适用于 525 行系统的服务集。 |
||
|
0x4401 |
适用于 625 行系统的服务集。 |
当应用程序在没有事先协商格式、切换视频标准(可能会使协商的 VBI 参数无效)和切换视频输入(可能会改变视频标准)后尝试读取或写入数据时,驱动程序可能会返回 EINVAL
错误代码。当应用程序在 I/O 正在进行时(在 ioctl VIDIOC_STREAMON, VIDIOC_STREAMOFF 和 VIDIOC_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 |
|
来自 切片 VBI 服务 的标志,用于标识此数据包中的数据类型。只能设置一位。当捕获的数据包的 |
__u32 |
|
此数据已从中捕获或将要插入的视频场号。 |
__u32 |
|
此数据已从中捕获或将要插入的场(而不是帧)行号。有关有效值,请参阅 图 4.2. ITU-R 525 行编号 (M/NTSC 和 M/PAL) 和 图 4.3. ITU-R 625 行编号。如果硬件无法可靠地识别扫描线,则切片 VBI 捕获设备可以将所有数据包的行号设置为 |
__u32 |
|
此字段保留用于未来的扩展。应用程序和驱动程序必须将其设置为零。 |
__u8 |
|
数据包有效载荷。有关每种数据类型传递的内容和字节数,请参阅 切片 VBI 服务。此数组末尾的填充字节的内容未定义,驱动程序和应用程序应忽略它们。 |
数据包始终按升序行号传递,没有重复的行号。当应用程序违反此规则时,write()
函数和 ioctl VIDIOC_QBUF, VIDIOC_DQBUF ioctl 必须返回 EINVAL
错误代码。当应用程序传递不正确的场号或行号,或与 VIDIOC_G_FMT 或 VIDIOC_S_FMT ioctl 未协商的 field
、line
和 id
的组合时,它们也必须返回 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 |
|
来自 结构体 v4l2_mpeg_vbi_fmt_ivtv 魔术字段的魔术常量 的一个“魔术”常量,它指示这是一个有效的切片 VBI 数据负载,并且还指示要使用匿名联合 |
union { |
(anonymous) |
|
struct |
|
切片 VBI 数据负载的主要形式,其中包含 1 到 35 行的切片 VBI 数据。此负载形式中提供了行掩码,指示提供了哪些 VBI 行。 |
struct v4l2_mpeg_vbi_ITV0 |
|
当存在 36 行切片 VBI 数据时,使用的切片 VBI 数据负载的替代形式。此负载形式不提供行掩码;所有有效的行掩码位均被隐式设置。 |
} |
4.7.5.4. 结构体 v4l2_mpeg_vbi_fmt_ivtv 魔术字段的魔术常量¶
定义的符号 |
值 |
描述 |
---|---|---|
|
“itv0” |
指示结构体 |
|
“ITV0” |
指示结构体 |
-
type v4l2_mpeg_vbi_itv0¶
-
type v4l2_mpeg_vbi_ITV0¶
4.7.5.5. 结构体 v4l2_mpeg_vbi_itv0 和 v4l2_mpeg_vbi_ITV0¶
__le32 |
|
指示存在的 VBI 服务行的位掩码。这些 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 |
|
这是一个可变长度的数组,保存 1 到 35 行的切片 VBI 数据。存在的切片 VBI 数据行与 |
4.7.5.6. 结构体 v4l2_mpeg_vbi_ITV0¶
struct |
|
一个固定长度的切片 VBI 数据数组,包含 36 行。 |
-
type v4l2_mpeg_vbi_itv0_line¶
4.7.5.7. 结构体 v4l2_mpeg_vbi_itv0_line¶
__u8 |
|
来自 结构体 v4l2_mpeg_vbi_itv0_line id 字段的行标识符常量 的行标识符值,指示此行上存储的切片 VBI 数据类型。 |
__u8 |
|
该行的切片 VBI 数据。 |
4.7.5.8. 结构体 v4l2_mpeg_vbi_itv0_line id 字段的行标识符¶
定义的符号 |
值 |
描述 |
---|---|---|
|
1 |
有关行负载的说明,请参阅 切片 VBI 服务。 |
|
4 |
有关行负载的说明,请参阅 切片 VBI 服务。 |
|
5 |
有关行负载的说明,请参阅 切片 VBI 服务。 |
|
7 |
有关行负载的说明,请参阅 切片 VBI 服务。 |