0%

H265 码流结构

H265 码流和是由很多 NAL Unit 组成,所有 NAL Unit 均存在一个 16 位数据的 NAL Unit Header ,一个 NAL Unit Header 的语法如下:

        +---------------+---------------+
        |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |F|   Type    |  LayerId  | TID |
        +-------------+-----------------+

Figure 1: The Structure of the H265 NAL Unit Header

描述符介绍

描述符描述了从比特流提取句法元素的方法,即句法元素的解码算法,每个句法元素都有相对应的描述符。由于 H.264 编码的最后一步是熵编码,所以这里的描述子大多是熵编码的解码算法。H.264 定义了如下几种描述符:

  • ae(v):基于上下文自适应的二进制算术熵编码
  • b(8):任意形式的 8 比特字节
  • ce(v):基于上下文自适应的可变长熵编码语法元素,左位在先
  • f(n):n 位固定模式比特串,左位在先
  • i(n)/i(v):n 比特的有符号整数,如果是 i(v),其比特数由其它语法元素值确定
  • me(v):映射指数哥伦布熵编码的语法元素,左位在先
  • se(v):有符号整数指数哥伦布熵编码的语法元素,左位在先
  • te(v):截断指数哥伦布熵编码语法元素,左位在先
  • u(n)/u(v):n 位无符号整数,如果是 u(v),其比特数由其它语法元素值确定
  • ue(v):无符号整数指数哥伦布编码的语法元素,左位在先

PPS 简介

除了序列参数集 SPS 之外,H.264 中另一重要的参数集合为图像参数集 Picture Paramater Set(PPS)。通常情况下,PPS 类似于 SPS,在 H.264 的裸码流中单独保存在一个 NAL Unit 中,只是 PPS NAL Unit 的 nal_unit_type 值为 8;而在封装格式中,PPS 通常与 SPS 一起,保存在视频文件的文件头中。

PPS 语法元素及其含义

在编解码过程中,如果需要使用 PPS 中包含的参数,必须对其中的数据进行解析。其中 H.264 标准协议中规定的 PPS 格式位于文档的 7.3.2.2 部分,如下图所示:

H264 码流结构

H264 码流是由很多 NAL Unit 组成,所有 NAL Unit 均存在一个八位数据的 NAL Unit Header ,这八位数据也充当此 RTP 有效负载格式的有效负载头。一个 NAL Unit Header 的语法如下:

    +---------------+
    |0|1|2|3|4|5|6|7|
    +-+-+-+-+-+-+-+-+
    |F|NRI|  Type   |
    +---------------+

Slice

一个 Slice 包含一帧图像的部分或全部数据,换言之,一帧视频图像可以编码为一个或若干个 Slice。一个 Slice 最少包含一个宏块,最多包含整帧图像的数据。在不同的编码实现中,同一帧图像中所构成的 Slice 数目不一定相同。

在 H.264 中设计 Slice 的目的主要在于防止误码的扩散。因为不同的 slice 之间,其解码操作是独立的。某一个 slice 的解码过程所参考的数据(例如预测编码)不能越过 slice 的边界。

NAL Unit 简介

NAL(Network Abstract Layer), 即网络抽象层。

在 H.264/AVC 视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL, Video Coding Layer)和网络抽象层面(NAL, Network Abstract Layer)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。

NAL unit 是 NAL 的基本语法结构,它包含一个字节的头信息和一系列来自 VCL 的称为拓展字节序列载荷(EBSP)的字节流。

帧 & 场

视频的一场或一帧可用来产生一个编码图像。通常,视频帧可分成两种类型:连续或隔行视频帧。

在电视中,为减少大面积闪烁现象,把一帧分成两个隔行的场。

显然,这时场内邻行之间的时间相关性较强,而帧内邻近行空间相关性强,因此活动量较小或静止的图像宜采用帧编码方式,对活动量较大的运动图像则宜采用场编码方式。

二叉树的节点

二叉树的节点定义

template <class T>
class BTNode{
    public:
        T value;            // 关键字 (键值)
        BSTNode *left;      // 左孩子
        BSTNode *right;     // 右孩子

        BSTNode(T v, BTNode *l = nullptr, BTNode *r = nullptr):
            value(v),left(l),right(r) {}
};

H.264 Level

在 H.264 标准中,有许多不同的 "级别" 指定约束,指示配置文件所需的解码器性能程度,这些 "级别" 即为 Level。Level 指定设备可以播放的最大数据速率和视频分辨率。

例如,配置文件中的支持级别将指定解码器可能能够使用的最大图像分辨率、帧速率和比特率。较低的级别意味着较低的分辨率、允许的最大比特率较低以及存储参考帧的内存要求更低。需要符合给定级别的解码器才能解码为该级别和所有较低级别编码的所有位流。

H.264 Profiles

2003 年,MPEG 完成了称为 MPEG-4 第 10 部分(H.264)的压缩标准的第一个版本。虽然 H.264 并不是唯一的压缩方法,但它已成为录制、压缩和流式处理高清视频最常用的格式。

H.264 是一个 "系列" 标准,包括许多不同的功能集, 即 profiles。所有的 profile 都严重依赖时态压缩和运动预测来减少帧数。最常用的三个配置文件是 Baseline, Main 和 High。每个 profile 定义用于压缩文件的特定编码技术和算法。

SPS 简介

在 H.264 标准协议中规定了多种不同的 NAL Unit 类型,其中类型 7 表示该 NAL Unit 内保存的数据为 Sequence Paramater Set(序列参数集)。

在 H.264 的各种语法元素中,SPS 中的信息至关重要。如果其中的数据丢失或出现错误,那么解码过程很可能会失败。

SPS 即 Sequence Paramater Set,又称作序列参数集。SPS 中保存了一组编码视频序列 (Coded videosequence) 的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况 SPS 和 PPS 的 NAL Unit 通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:

  • 解码器需要在码流中间开始解码
  • 编码器在编码的过程中改变了码流的参数(如图像分辨率等)

源码阅读 x264 - 命令行工具 中我们分析到 encode() 的流程中涉及到 libx264 的几个关键的 API,这些函数有:

  • x264_encoder_open():打开 H.264 编码器。
  • x264_encoder_headers():输出 SPS/PPS/SEI。
  • x264_encoder_encode():编码一帧数据。
  • x264_encoder_close():关闭 H.264 编码器。

本文主要对 x264 中的重要结构体进行介绍,包括的结构体有:

  • struct x264_param_t
  • struct cli_opt_t
  • 更多结构体更新中