目录

2.3 时间单元

2.4 随机访问点

2.3 时间单元

为了更加清晰地描述 AV1 比特流,AV1 引入了时间单元(Temporal Unit,TU)的概念。如 AV1 标准文档 7.5 节所述,符合 AV1 规范的比特流由一个或多个编码视频序列组成。一个编码视频序列由一个或多个时间单元构成。而时间单元则是由一个时间分隔符 OBU 和所有在此之后并且在下一个时间分隔符 OBU 之前的 OBU 组成。这些 OBU 包含时间分隔符 OBU、序列头 OBU、元数据 OBU、帧头 OBU、切片组 OBU 以及填充 OBU。其中,时间分隔符 OBU 用于指示时间单元的开始,序列头 OBU 和元数据 OBU 包含了与整个序列相关的信息,帧头 OBU 和切片组 OBU 包含了与单个帧相关的信息,填充 OBU 用于填充数据以满足特定的编码要求。

时间单元始终按照递增的显示顺序排列。如果不使用可扩展性编码,则时间单元恰好包含一个显示帧,即show_existing_frame等于 1 或show_frame等于 1 的帧。如果使用可扩展性编码,则一个时间单元可能包含来自不同扩展层(Scalable Layer)的所有显示帧,这些显示帧具有相同的显示时间。这里需要注意的是,时间单元必须包含显示帧,同时也可以包含语法元素show_frame等于 0 的视频帧。由于重叠帧的show_frame等于 1,因此时间单元中的显示帧可以是重叠帧(Overlay Frame)。关于重叠帧的详细介绍,请参考第 4 章。因此,可以认为一个时间单元由一个显示帧和 0 个或多个非显示帧组成。

图 2-3 所示为比特流中时间单元划分示例。图 2-3a 展示了 GOP 长度等于 4 帧的金字塔预测编码结构,其中矩形框中的数字表示编码顺序,横坐标轴表示显示顺序。图 2-3b 展示了图 2-3a 的码流结构中的时间单元划分方式,其中 TD 表示时间分隔符,TU 表示时间单元,SeqHdr 表示序列头信息。在图 2-3b 中,标记 “帧 x/y” 的矩形表示编码帧数据,x 是编码顺序,y 是显示顺序。“帧 0/0” 和 “帧 3/1” 的语法元素show_frame等于 1,表示解码之后立即输出。“帧 0/0” 使用 TU0 的时间分隔符所指示的时间戳,而 “帧 3/1” 使用 TU1 的时间分隔符所指示的时间戳。“帧 1/4” 和 “帧 2/2” 的语法元素show_frame等于 0,表示解码之后不能立即输出。FrameHdr2 是一个帧头信息,其中的show_existing_frame等于 1 并且frame_to_show_map_idx指向先前已经解码的 “帧 2/2”。这种操作表示,此时要输出 “帧 2/2”,它使用的是 TU2 的时间分隔符所指示的时间戳。

图 2-3 比特流中时间单元划分示例

关于时间单元,有以下几点需要注意:

  • 在一个时间单元内,帧头和与之相关的切片组 OBU 必须使用相同的obu_extension_flag值。也就是说,如果一个帧头包括可选的 OBU 扩展头信息,那么与之相关的所有切片组 OBU 也必须包括可选的 OBU 扩展头信息;如果一个帧头不包含可选的 OBU 扩展头信息,那么与之相关的所有切片组 OBU 也不能包含可选的 OBU 扩展头信息。
  • 对于位于同一个时间单元之内的所有 OBU 扩展头,当这些 OBU 扩展头的spatial_id都相同时,它们的temporal_id也必须相同。
  • 并不是每个包含关键帧的时间单元都必须包含序列头,只是要求序列头在第一个关键帧之前已经发送。但是,没有序列头 OBU 的时间单元不被视为随机访问点(Random Access Point)。

基于时间单元的概念,每个新的编码视频序列都定义为从满足以下两个条件的每个时间单元开始:

  1. 第一个帧头 OBU 之前包含一个或多个序列头 OBU。
  2. 第一个帧头信息中的语法元素frame_type=KEY_FRAMEshow_frame=1show_existing_frame=0temporal_id=0

如果不使用可扩展性编码,则所有视频帧都是操作点的一部分。此时,操作点必须满足以下约束条件:

  • 第一个帧头信息中的语法元素frame_type=KEY_FRAMEshow_frame=1
  • 每个时间单元恰好包含一个显示帧,即show_existing_frame=1show_frame=1

如果使用了可扩展性编码,此时会有多个操作点。每个操作点必须满足以下约束条件:

  • 即将解码的第一个帧头信息必须包含语法元素frame_typeshow_frame,并且frame_type=KEY_FRAMEshow_frame=1
  • 在一个时间单元中,每个具有编码帧的层必须有一个显示帧,该显示帧是该层在时间单元中的最后一帧;

2.4 随机访问点

一般来说,随机访问点是比特流中可以开始解码的位置。在视频编码中,随机访问点是一种特殊的编码帧,它可以使解码器在这个位置开始解码,而不需要解码之前的数据。这样可以提高视频的随机访问性能,使用户可以快速地跳转到视频的任意位置进行播放。

AV1 定义了 3 种随机访问点。为了满足最基本的功能要求,解码器必须支持这 3 种随机访问点。但是,在实现过程中,解码器可以选择支持更多类型的随机访问点。AV1 定义的 3 种随机访问点包括:关键帧随机访问点(Key Frame Random Access Point,KFRAP)、延迟随机访问点(Delayed Random Access Point,DRAP)和关键帧依赖帧恢复点(Key Frame Dependent Recovery Point,KFDRP)。它们的定义如下:

  • ** 关键帧随机访问点(KFRAP)** 是一个满足下述条件的帧:
    • frame_type=KEY_FRAME
    • show_frame=1
    • 包含关键帧随机访问点的时间单元包含序列头 OBU
  • ** 延迟随机访问点(DRAP)** 是一个满足下述条件的帧:
    • frame_type=KEY_FRAME
    • show_frame=0
    • 包含延迟随机访问点的时间单元包含序列头 OBU
  • ** 关键帧依赖恢复点(KFDRP)** 是一个满足下述条件的帧:
    • show_existing_frame=1
    • frame_to_show_map_idx指定了一个要输出的帧,这个帧是一个延迟随机访问点

从上述定义可见,延迟随机访问点和关键帧依赖恢复点需要搭配使用才可以实现随机访问。从关键帧随机访问点开始解码是很简单的,因为如果关键帧随机访问点之前的时间单元被丢弃,剩余的时间单元仍然构成一个有效的比特流。但是,从延迟随机访问点开始解码的行为却很难定义。这是因为:

  1. 如果在关键帧依赖恢复点之前的所有时间单元都被丢弃了,那么在这种情况下,由于关键帧依赖恢复点依赖于其前面的延迟随机访问点,并且相关的延迟随机访问点已经被丢弃,因此不能正常解码。
  2. 如果在延迟随机访问点之前的所有时间单元都被丢弃了,那么,对位于延迟随机访问点和关键帧依赖恢复点之间的帧应该如何处理并没有明确规定,比如有些应用可能希望丢弃这些帧,而其他应用可能希望保留这些帧。

综合这两种情况,由于从延迟随机访问点开始解码并不是从一个显示关键帧开始解码,因此剩余的时间单元不构成一个有效的比特流。为了支持不同的操作模式,需要一个符合规范的解码器来解码下面的比特流:

  • 包含一个延迟随机访问点的时间单元
  • 包含相关的关键帧依赖恢复点的时间单元
  • 可选的额外时间单元

也就是说,符合规范的解码器要能够解码上述结构的比特流。这将是否丢弃中间时间单元(位于延迟随机访问点和关键帧依赖恢复点之间的时间单元)的操作从规范定义的解码过程中转移到了特定应用的行为上。这允许应用程序根据应用场景和特定解码器实现的能力选择使用哪种行为。

实际上,预期解码器实现能够在中间时间单元仍然存在的情况下,从延迟随机访问点开始解码比特流。解码器应该从下一个关键帧或关键帧依赖恢复点开始,正确地解码产生所有要输出的帧。而下一个关键帧或关键帧依赖恢复点之前的视频帧则由具体的编码器实现来决定如何处理。例如:

  • 当参考帧不可用时,由于流媒体解码器能够容忍输出视频有一些错误,因此流媒体解码器可能选择解码并显示所有帧。
  • 而低延迟解码器可能选择解码并显示所有保证正确的帧,即输出那些仅以关键帧依赖恢复点为参考帧的帧间预测帧。
  • 媒体播放器解码器可能选择仅从关键帧或关键帧依赖恢复点开始解码和显示帧,以保证流畅播放。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐