3.5. 缓冲区

缓冲区包含应用程序和驱动程序使用流式 I/O 方法之一交换的数据。在多平面 API 中,数据保存在平面中,而缓冲区结构充当平面的容器。仅交换指向缓冲区(平面)的指针,数据本身不进行复制。这些指针以及时间戳或场奇偶校验等元信息存储在 v4l2_buffer 结构中,该结构是 ioctl VIDIOC_QUERYBUFVIDIOC_QBUFVIDIOC_DQBUF ioctl 的参数。在多平面 API 中,v4l2_buffer 结构的一些特定于平面的成员,例如每个平面的指针和大小,存储在 v4l2_plane 结构中。在这种情况下,v4l2_buffer 包含一个平面结构数组。

出队的视频缓冲区带有时间戳。驱动程序决定在帧的哪个部分以及使用哪个时钟获取时间戳。请参阅 缓冲区标志 中的 V4L2_BUF_FLAG_TIMESTAMP_MASKV4L2_BUF_FLAG_TSTAMP_SRC_MASK 掩码中的标志。这些标志在整个视频流期间始终有效且恒定。这些标志的更改可能会作为 VIDIOC_S_INPUTVIDIOC_S_OUTPUT 的副作用发生。例如,mem-to-mem 设备使用的 V4L2_BUF_FLAG_TIMESTAMP_COPY 时间戳类型是该规则的例外:时间戳源标志从 OUTPUT 视频缓冲区复制到 CAPTURE 视频缓冲区。

3.5.1. 格式、控件和缓冲区之间的交互

V4L2 公开了影响缓冲区大小或数据在缓冲区中布局方式的参数。这些参数通过格式和控件公开。这种控件的一个示例是 V4L2_CID_ROTATE 控件,该控件会修改像素在缓冲区中存储的方向,以及当所选格式在行尾包含填充时缓冲区的尺寸。

解释缓冲区内容所需的信息集(例如,像素格式、行步幅、平铺方向或旋转)在本节的其余部分中统称为缓冲区布局。

可以修改缓冲区布局的控件应设置 V4L2_CTRL_FLAG_MODIFY_LAYOUT 标志。

修改影响缓冲区大小或布局的格式或控件需要停止流。任何在流活动时尝试进行此类修改的操作都应导致设置格式或控件的 ioctl 返回 EBUSY 错误代码。在这种情况下,当流活动时,驱动程序还应在调用 VIDIOC_QUERYCTRL()VIDIOC_QUERY_EXT_CTRL() 时,为此类控件设置 V4L2_CTRL_FLAG_GRABBED 标志。

注意

VIDIOC_S_SELECTION() ioctl 可以根据硬件(例如,如果设备不包含缩放器)修改格式以及选择矩形。类似地,VIDIOC_S_INPUT()VIDIOC_S_OUTPUT()VIDIOC_S_STD()VIDIOC_S_DV_TIMINGS() ioctl 也可以修改格式和选择矩形。当这些 ioctl 导致缓冲区大小或布局更改时,驱动程序应像处理 VIDIOC_S_FMT() ioctl 中所述的所有情况一样处理该条件。

仅影响缓冲区布局的控件可以在流停止时随时修改。由于它们不影响缓冲区大小,因此无需进行特殊处理来将这些控件与缓冲区分配同步,并且一旦流停止,V4L2_CTRL_FLAG_GRABBED 标志将被清除。

影响缓冲区大小的格式和控件与缓冲区分配交互。处理此问题的最简单方法是驱动程序始终要求重新分配缓冲区,以便更改这些格式或控件。在这种情况下,要执行此类更改,用户空间应用程序应首先使用 VIDIOC_STREAMOFF() ioctl 停止正在运行的视频流,如果分配了所有缓冲区,则使用 VIDIOC_REQBUFS() ioctl 释放所有缓冲区。释放所有缓冲区后,控件的 V4L2_CTRL_FLAG_GRABBED 标志将被清除。然后可以修改格式或控件,然后应重新分配缓冲区并重新启动流。典型的 ioctl 序列是

  1. VIDIOC_STREAMOFF

  2. VIDIOC_REQBUFS(0)

  3. VIDIOC_S_EXT_CTRLS

  4. VIDIOC_S_FMT

  5. VIDIOC_REQBUFS(n)

  6. VIDIOC_QBUF

  7. VIDIOC_STREAMON

第二个 VIDIOC_REQBUFS() 调用将考虑新的格式和控制值,以计算要分配的缓冲区大小。如果需要,应用程序还可以通过调用 VIDIOC_G_FMT() ioctl 来检索大小。

注意

API 没有强制要求控件 (3.) 和格式 (4.) 更改的上述顺序。可以根据设备和用例以不同的顺序设置格式和控件,甚至可以交错设置。例如,某些控件对于不同的像素格式的行为可能不同,在这种情况下,可能需要首先设置格式。

当需要重新分配时,任何在分配缓冲区时尝试修改影响缓冲区大小的格式或控件的操作都应导致格式或控件设置 ioctl 返回 EBUSY 错误。任何尝试排队对于当前格式或控件而言太小的缓冲区的操作都应导致 VIDIOC_QBUF() ioctl 返回 EINVAL 错误。

缓冲区重新分配是一项昂贵的操作。为了避免这种开销,驱动程序可以(并鼓励)允许在分配缓冲区的情况下更改影响缓冲区大小的格式或控件。在这种情况下,修改格式和控件的典型 ioctl 序列是

  1. VIDIOC_STREAMOFF

  2. VIDIOC_S_EXT_CTRLS

  3. VIDIOC_S_FMT

  4. VIDIOC_QBUF

  5. VIDIOC_STREAMON

为了使此序列正常工作,排队的缓冲区需要足够大,才能容纳新的格式或控件。如果当前排队了对于新格式而言太小的缓冲区,则驱动程序应在响应格式更改 (VIDIOC_S_FMT()) 或控件更改 (VIDIOC_S_CTRL()VIDIOC_S_EXT_CTRLS()) 时返回 ENOSPC 错误。为简化起见,如果当前排队了任何缓冲区,则允许驱动程序从这些 ioctl 返回 EBUSY 错误,而无需检查排队的缓冲区大小。

此外,如果排队的缓冲区对于当前格式或控件而言太小,则驱动程序应从 VIDIOC_QBUF() ioctl 返回 EINVAL 错误。这些要求共同确保排队的缓冲区始终足够大,以满足配置的格式和控件。

用户空间应用程序可以通过首先设置所需的控件值,然后尝试所需的格式来查询给定格式和控件所需的缓冲区大小。VIDIOC_TRY_FMT() ioctl 将返回所需的缓冲区大小。

  1. VIDIOC_S_EXT_CTRLS(x)

  2. VIDIOC_TRY_FMT()

  3. VIDIOC_S_EXT_CTRLS(y)

  4. VIDIOC_TRY_FMT()

然后可以使用 VIDIOC_CREATE_BUFS() ioctl 根据查询的大小分配缓冲区(例如,通过分配一组足够大的缓冲区来容纳所有所需的格式和控件,或者通过为每个用例分配单独的一组大小合适的缓冲区)。

type v4l2_buffer

3.5.2. struct v4l2_buffer

struct v4l2_buffer

__u32

index

缓冲区编号,由应用程序设置,除非调用 VIDIOC_DQBUF,此时由驱动程序设置。此字段的范围从零到使用 ioctl VIDIOC_REQBUFS ioctl (struct v4l2_requestbuffers count) 分配的缓冲区数量,再加上使用 ioctl VIDIOC_CREATE_BUFS 分配的任何缓冲区数量,再减一。

__u32

type

缓冲区类型,与 struct v4l2_format type 或 struct v4l2_requestbuffers type 相同,由应用程序设置。请参阅 v4l2_buf_type

__u32

bytesused

缓冲区中数据占用的字节数。它取决于协商的数据格式,并且对于诸如 JPEG 图像之类的压缩可变大小数据,每个缓冲区可能会发生变化。当 type 指的是捕获流时,驱动程序必须设置此字段;当它指的是输出流时,应用程序必须设置此字段。对于多平面格式,此字段将被忽略,而是使用 planes 指针。

__u32

flags

应用程序或驱动程序设置的标志,请参阅 缓冲区标志

__u32

field

指示缓冲区中图像的场序,请参阅 v4l2_field。当缓冲区包含 VBI 数据时,不使用此字段。当 type 指的是捕获流时,驱动程序必须设置此字段;当它指的是输出流时,应用程序必须设置此字段。

struct timeval

timestamp

对于捕获流,这是捕获第一个数据字节的时间,由相关时钟 ID 的 clock_gettime() 函数返回;请参阅 缓冲区标志 中的 V4L2_BUF_FLAG_TIMESTAMP_*。对于输出流,驱动程序将最后一个数据字节实际发送出去的时间存储在 timestamp 字段中。这允许应用程序监视视频和系统时钟之间的漂移。对于使用 V4L2_BUF_FLAG_TIMESTAMP_COPY 的输出流,应用程序必须填写时间戳,该时间戳将由驱动程序复制到捕获流。

struct v4l2_timecode

timecode

flags 中设置了 V4L2_BUF_FLAG_TIMECODE 标志时,此结构包含帧时间码。在 V4L2_FIELD_ALTERNATE 模式下,顶部和底部场包含相同的时间码。时间码旨在帮助视频编辑,通常记录在录像带上,但也嵌入在诸如 MPEG 之类的压缩格式中。此字段独立于 timestampsequence 字段。

__u32

sequence

由驱动程序设置,按顺序计算帧(不是场!)。此字段针对输入和输出设备设置。

V4L2_FIELD_ALTERNATE 模式下,顶部和底部场具有相同的序列号。计数从零开始,包括丢弃或重复的帧。丢弃的帧是由输入设备接收的,但由于缺少可用缓冲区空间而无法存储。重复的帧是由于应用程序没有及时传递新数据而由输出设备再次显示的。

注意

这可以计算例如通过 USB 接收的帧,而不考虑由于有限的压缩吞吐量或总线带宽而被远程硬件丢弃的帧。这些设备通过不枚举任何视频标准来识别,请参阅 视频标准

__u32

memory

此字段必须由应用程序和/或驱动程序根据选择的 I/O 方法设置。请参阅 v4l2_memory

union {

m

__u32

offset

对于单平面 API 并且当 memoryV4L2_MEMORY_MMAP 时,这是缓冲区相对于设备内存起始位置的偏移量。该值由驱动程序返回,除了作为 mmap() 函数的参数外,对于应用程序没有用处。有关详细信息,请参阅 流式 I/O(内存映射)

unsigned long

userptr

对于单平面 API 并且当 memoryV4L2_MEMORY_USERPTR 时,这是指向虚拟内存中缓冲区的指针(转换为无符号长整型),由应用程序设置。有关详细信息,请参阅 流式 I/O(用户指针)

struct v4l2_plane

*planes

当使用多平面 API 时,包含指向 struct v4l2_plane 数组的用户空间指针。数组的大小应放在此 struct v4l2_buffer 结构的 length 字段中。

int

fd

对于单平面 API 并且当 memoryV4L2_MEMORY_DMABUF 时,这是与 DMABUF 缓冲区关联的文件描述符。

}

__u32

length

对于单平面 API,以字节为单位的缓冲区大小(不是有效负载)。这是由驱动程序根据对 ioctl VIDIOC_REQBUFS 和/或 ioctl VIDIOC_CREATE_BUFS 的调用设置的。对于多平面 API,应用程序将此设置为 planes 数组中的元素数量。驱动程序将填写该数组中有效元素的实际数量。

__u32

reserved2

用于未来扩展的占位符。驱动程序和应用程序必须将其设置为 0。

__u32

request_fd

要将缓冲区排队的请求的文件描述符。如果设置了标志 V4L2_BUF_FLAG_REQUEST_FD,则会将缓冲区排队到此请求。如果未设置该标志,则将忽略此字段。

V4L2_BUF_FLAG_REQUEST_FD 标志和此字段仅由 ioctl VIDIOC_QBUF 使用,并且会被其他使用 v4l2_buffer 作为参数的 ioctl 忽略。

对于 VIDIOC_QBUF 以外的任何 ioctl,应用程序不应设置 V4L2_BUF_FLAG_REQUEST_FD

如果设备不支持请求,则将返回 EBADR。如果支持请求但给出了无效的请求文件描述符,则将返回 EINVAL

type v4l2_plane

3.5.3. struct v4l2_plane

__u32

bytesused

平面中数据占用的字节数(其有效负载)。当 type 指的是捕获流时,驱动程序必须设置此字段;当它指的是输出流时,应用程序必须设置此字段。

注意

请注意,实际的图像数据从 data_offset 开始,该值可能不为 0。

__u32

length

平面的字节大小(不是其有效负载)。这是由驱动程序根据对 ioctl VIDIOC_REQBUFS 和/或 ioctl VIDIOC_CREATE_BUFS 的调用设置的。

union {

m

__u32

mem_offset

当包含结构体 v4l2_buffer 中的内存类型为 V4L2_MEMORY_MMAP 时,这是应该传递给 mmap() 的值,类似于结构体 v4l2_buffer 中的 offset 字段。

unsigned long

userptr

当包含结构体 v4l2_buffer 中的内存类型为 V4L2_MEMORY_USERPTR 时,这是一个用户空间指针,指向应用程序为此平面分配的内存。

int

fd

当包含结构体 v4l2_buffer 中的内存类型为 V4L2_MEMORY_DMABUF 时,这是一个与 DMABUF 缓冲区关联的文件描述符,类似于结构体 v4l2_buffer 中的 fd 字段。

}

__u32

data_offset

平面中视频数据的字节偏移量。当 type 指的是捕获流时,驱动程序必须设置此字段;当它指的是输出流时,应用程序必须设置此字段。

注意

该 data_offset 包含在 bytesused 中。因此,平面中图像的大小为 bytesused-data_offset,偏移量为平面起始位置的 data_offset

__u32

reserved[11]

保留供将来使用。驱动程序和应用程序应将其置零。

type v4l2_buf_type

3.5.4. enum v4l2_buf_type

V4L2_BUF_TYPE_VIDEO_CAPTURE

1

单平面视频捕获流的缓冲区,请参阅 视频捕获接口

V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE

9

多平面视频捕获流的缓冲区,请参阅 视频捕获接口

V4L2_BUF_TYPE_VIDEO_OUTPUT

2

单平面视频输出流的缓冲区,请参阅 视频输出接口

V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE

10

多平面视频输出流的缓冲区,请参阅 视频输出接口

V4L2_BUF_TYPE_VIDEO_OVERLAY

3

用于视频叠加的缓冲区,请参阅 视频叠加接口

V4L2_BUF_TYPE_VBI_CAPTURE

4

原始 VBI 捕获流的缓冲区,请参阅 原始 VBI 数据接口

V4L2_BUF_TYPE_VBI_OUTPUT

5

原始 VBI 输出流的缓冲区,请参阅 原始 VBI 数据接口

V4L2_BUF_TYPE_SLICED_VBI_CAPTURE

6

切片 VBI 捕获流的缓冲区,请参阅 切片 VBI 数据接口

V4L2_BUF_TYPE_SLICED_VBI_OUTPUT

7

切片 VBI 输出流的缓冲区,请参阅 切片 VBI 数据接口

V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY

8

用于视频输出叠加 (OSD) 的缓冲区,请参阅 视频输出叠加接口

V4L2_BUF_TYPE_SDR_CAPTURE

11

用于软件定义无线电 (SDR) 捕获流的缓冲区,请参阅 软件定义无线电接口 (SDR)

V4L2_BUF_TYPE_SDR_OUTPUT

12

用于软件定义无线电 (SDR) 输出流的缓冲区,请参阅 软件定义无线电接口 (SDR)

V4L2_BUF_TYPE_META_CAPTURE

13

用于元数据捕获的缓冲区,请参阅 元数据接口

V4L2_BUF_TYPE_META_OUTPUT

14

用于元数据输出的缓冲区,请参阅 元数据接口

3.5.5. 缓冲区标志

V4L2_BUF_FLAG_MAPPED

0x00000001

缓冲区驻留在设备内存中,并且已映射到应用程序的地址空间中,有关详细信息,请参阅 流式 I/O(内存映射)。当调用 ioctl VIDIOC_QUERYBUFioctl VIDIOC_QBUF, VIDIOC_DQBUFVIDIOC_DQBUF ioctl 时,驱动程序会设置或清除此标志。由驱动程序设置。

V4L2_BUF_FLAG_QUEUED

0x00000002

在内部,驱动程序维护两个缓冲区队列,一个传入队列和一个传出队列。当设置此标志时,该缓冲区当前位于传入队列上。在缓冲区被填充(捕获设备)或显示(输出设备)后,它会自动移动到传出队列。当调用 VIDIOC_QUERYBUF ioctl 时,驱动程序会设置或清除此标志。在(成功)调用 VIDIOC_QBUF ioctl 之后,它始终被设置;在 VIDIOC_DQBUF 之后,它始终被清除。

V4L2_BUF_FLAG_DONE

0x00000004

当设置此标志时,该缓冲区当前位于传出队列上,准备好从驱动程序中出队。当调用 VIDIOC_QUERYBUF ioctl 时,驱动程序会设置或清除此标志。在调用 VIDIOC_QBUFVIDIOC_DQBUF 之后,它始终被清除。当然,一个缓冲区不能同时位于两个队列上,V4L2_BUF_FLAG_QUEUEDV4L2_BUF_FLAG_DONE 标志是互斥的。但是,它们都可以被清除,此时缓冲区处于“出队”状态,即处于应用程序域中。

V4L2_BUF_FLAG_ERROR

0x00000040

当设置此标志时,该缓冲区已成功出队,但数据可能已损坏。这是可恢复的,流式传输可以正常继续,并且可以正常重复使用该缓冲区。当调用 VIDIOC_DQBUF ioctl 时,驱动程序会设置此标志。

V4L2_BUF_FLAG_IN_REQUEST

0x00000080

此缓冲区是尚未入队的请求的一部分。

V4L2_BUF_FLAG_KEYFRAME

0x00000008

当调用 VIDIOC_DQBUF ioctl 时,驱动程序会设置或清除此标志。当缓冲区包含可自行解压缩的压缩图像(即关键帧或场)时,视频捕获设备可能会设置此标志。也称为 I 帧。当 type 指的是输出流时,应用程序可以设置此位。

V4L2_BUF_FLAG_PFRAME

0x00000010

类似于 V4L2_BUF_FLAG_KEYFRAME,此标志表示预测帧或场,其中仅包含与上一个关键帧的差异。当 type 指的是输出流时,应用程序可以设置此位。

V4L2_BUF_FLAG_BFRAME

0x00000020

类似于 V4L2_BUF_FLAG_KEYFRAME,此标志表示双向预测帧或场,其中仅包含当前帧与前面和后面的关键帧之间的差异,以指定其内容。当 type 指的是输出流时,应用程序可以设置此位。

V4L2_BUF_FLAG_TIMECODE

0x00000100

timecode 字段有效。当调用 VIDIOC_DQBUF ioctl 时,驱动程序会设置或清除此标志。当 type 指的是输出流时,应用程序可以设置此位以及相应的 timecode 结构。

V4L2_BUF_FLAG_PREPARED

0x00000400

缓冲区已准备好进行 I/O,并且可以由应用程序入队。当调用 VIDIOC_QUERYBUFVIDIOC_PREPARE_BUFVIDIOC_QBUFVIDIOC_DQBUF ioctl 时,驱动程序会设置或清除此标志。

V4L2_BUF_FLAG_NO_CACHE_INVALIDATE

0x00000800

无需使此缓冲区的缓存失效。通常,如果 CPU 不会接触缓冲区中捕获的数据,则应用程序应使用此标志,相反,该缓冲区可能会传递给支持 DMA 的硬件单元以进行进一步处理或输出。除非队列用于 内存映射 流式 I/O 并报告 V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS 功能,否则将忽略此标志。

V4L2_BUF_FLAG_NO_CACHE_CLEAN

0x00001000

此缓冲区不需要清除缓存。通常,如果此缓冲区中的数据不是由 CPU 创建,而是由某些具有 DMA 功能的单元创建的,则应用程序应将此标志用于输出缓冲区,在这种情况下,未使用缓存。除非队列用于 内存映射 流式 I/O 并报告 V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS 功能,否则将忽略此标志。

V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF

0x00000200

仅当设置了 struct v4l2_requestbuffers 标志 V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF 时有效。它通常与无状态解码器一起使用,其中多个输出缓冲区各自解码为解码帧的一个切片。应用程序可以在排队输出缓冲区时设置此标志,以防止驱动程序在解码输出缓冲区后将捕获缓冲区出队(即,捕获缓冲区被“保持”)。如果此输出缓冲区的时间戳与前一个输出缓冲区的时间戳不同,则表示新帧的开始,并且之前保持的捕获缓冲区将被出队。

V4L2_BUF_FLAG_LAST

0x00100000

硬件产生的最后一个缓冲区。当调用 ioctl VIDIOC_QUERYBUFVIDIOC_DQBUF ioctl 时,mem2mem 编解码器驱动程序会在捕获队列上设置此标志,用于最后一个缓冲区。由于硬件限制,最后一个缓冲区可能为空。在这种情况下,无论格式如何,驱动程序都会将 bytesused 字段设置为 0。任何后续对 VIDIOC_DQBUF ioctl 的调用都不会再阻塞,而是返回 EPIPE 错误代码。

V4L2_BUF_FLAG_REQUEST_FD

0x00800000

request_fd 字段包含有效的文件描述符。

V4L2_BUF_FLAG_TIMESTAMP_MASK

0x0000e000

下面时间戳类型的掩码。要测试时间戳类型,请通过使用缓冲区标志和时间戳掩码执行逻辑与运算来屏蔽掉不属于时间戳类型的位。

V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN

0x00000000

未知的时间戳类型。此类型由 Linux 3.9 之前的驱动程序使用,可以是单调的(见下文)或实时的(挂钟时间)。单调时钟在嵌入式系统中更受欢迎,而大多数驱动程序使用实时时钟。用户空间可以通过使用时钟 ID CLOCK_MONOTONICCLOCK_REALTIME 分别使用 clock_gettime() 来访问两种类型的时间戳。

V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC

0x00002000

缓冲区时间戳取自 CLOCK_MONOTONIC 时钟。要在 V4L2 外部访问同一时钟,请使用 clock_gettime()

V4L2_BUF_FLAG_TIMESTAMP_COPY

0x00004000

CAPTURE 缓冲区时间戳取自相应的 OUTPUT 缓冲区。此标志仅适用于 mem2mem 设备。

V4L2_BUF_FLAG_TSTAMP_SRC_MASK

0x00070000

下面时间戳源的掩码。时间戳源定义了时间戳相对于帧的获取时间点。 flags 字段和 V4L2_BUF_FLAG_TSTAMP_SRC_MASK 之间的逻辑“与”运算会产生时间戳源的值。当 type 指的是输出流并且设置了 V4L2_BUF_FLAG_TIMESTAMP_COPY 时,应用程序必须设置时间戳源。

V4L2_BUF_FLAG_TSTAMP_SRC_EOF

0x00000000

帧结束。当接收到帧的最后一个像素或已传输帧的最后一个像素时,会获取缓冲区时间戳。在实践中,软件生成的时间戳通常会在接收或传输最后一个像素后的一小段时间从时钟读取,具体取决于系统及其中的其他活动。

V4L2_BUF_FLAG_TSTAMP_SRC_SOE

0x00010000

曝光开始。当帧的曝光开始时会获取缓冲区时间戳。这仅对 V4L2_BUF_TYPE_VIDEO_CAPTURE 缓冲区类型有效。

3.5.6. enum v4l2_memory

V4L2_MEMORY_MMAP

1

该缓冲区用于 内存映射 I/O。

V4L2_MEMORY_USERPTR

2

该缓冲区用于 用户指针 I/O。

V4L2_MEMORY_OVERLAY

3

[待办]

V4L2_MEMORY_DMABUF

4

该缓冲区用于 DMA 共享缓冲区 I/O。

3.5.7. 时间码

v4l2_buffer_timecode 结构旨在保存 SMPTE 12M 或类似的时间码。(struct timeval 时间戳存储在 struct v4l2_buffer timestamp 字段中。)

类型 v4l2_timecode

3.5.7.1. struct v4l2_timecode

__u32

type

时间码所基于的帧速率,请参阅 时间码类型

__u32

flags

时间码标志,请参阅 时间码标志

__u8

frames

帧计数,0 ... 23/24/29/49/59,具体取决于时间码的类型。

__u8

seconds

秒计数,0 ... 59。这是一个二进制数,而不是 BCD 数。

__u8

minutes

分钟计数,0 ... 59。这是一个二进制数,而不是 BCD 数。

__u8

hours

小时计数,0 ... 29。这是一个二进制数,而不是 BCD 数。

__u8

userbits[4]

时间码中的“用户组”位。

3.5.7.2. 时间码类型

V4L2_TC_TYPE_24FPS

1

每秒 24 帧,即电影。

V4L2_TC_TYPE_25FPS

2

每秒 25 帧,即 PAL 或 SECAM 视频。

V4L2_TC_TYPE_30FPS

3

每秒 30 帧,即 NTSC 视频。

V4L2_TC_TYPE_50FPS

4

V4L2_TC_TYPE_60FPS

5

3.5.7.3. 时间码标志

V4L2_TC_FLAG_DROPFRAME

0x0001

指示以 29.97 fps 材料计数帧的“丢帧”语义。设置后,每分钟开始的帧号 0 和 1 将从计数中省略,但分钟 0、10、20、30、40、50 除外。

V4L2_TC_FLAG_COLORFRAME

0x0002

“彩色帧”标志。

V4L2_TC_USERBITS_field

0x000C

“二进制组标志”的字段掩码。

V4L2_TC_USERBITS_USERDEFINED

0x0000

未指定的格式。

V4L2_TC_USERBITS_8BITCHARS

0x0008

8 位 ISO 字符。