Skip to main content

3.1.1.3.2. Sequences_Section (序列段)

压缩块是一系列序列的连续体。序列是一个字面量复制命令,后跟一个匹配复制命令。字面量复制命令指定长度。它是要从 Literals_Section 复制(或提取)的字节数。匹配复制命令指定偏移量和长度。

当所有序列都已解码后,如果 Literals_Section 中还有剩余字面量,则这些字节将添加到块的末尾。

这在第 3.1.1.4 节中有更详细的描述。

Sequences_Section 重新组合解码命令所需的所有符号。有三种符号类型:字面量长度代码、偏移量代码和匹配长度代码。它们在单个 "位流" 中交错编码在一起。

Sequences_Section 以头部开始,然后是每种符号类型的可选概率表,然后是位流。

Sequences_Section_Header
[Literals_Length_Table]
[Offset_Table]
[Match_Length_Table]
bitStream

要解码 Sequences_Section,必须知道其大小。此大小从 Literals_Section 的大小推导出来:

Sequences_Section_Size = Block_Size - Literals_Section_Header 
- Literals_Section_Content

3.1.1.3.2.1. Sequences_Section_Header (序列段头部)

此头部由两个项目组成:

  • Number_of_Sequences (序列数量)
  • Symbol_Compression_Modes (符号压缩模式)

Number_of_Sequences

Number_of_Sequences 是一个可变大小字段,使用 1 到 3 个字节。如果第一个字节是 "byte0":

  • if (byte0 == 0): 没有序列。序列部分在此停止。解压缩内容完全定义为 Literals_Section 内容。Repeat_Mode 中使用的 FSE 表不会更新。

  • if (byte0 < 128): Number_of_Sequences = byte0。使用 1 字节。

  • if (byte0 < 255): Number_of_Sequences = ((byte0 - 128) << 8) + byte1。使用 2 字节。

  • if (byte0 == 255): Number_of_Sequences = byte1 + (byte2 << 8) + 0x7F00。使用 3 字节。

Symbol_Compression_Modes

Symbol_Compression_Modes 是一个单字节,定义每种符号类型的压缩模式。

比特号 (Bit Number)字段名称 (Field Name)
7-6Literal_Lengths_Mode
5-4Offsets_Mode
3-2Match_Lengths_Mode
1-0Reserved (保留)

表 14: Symbol_Compression_Modes

最后一个字段 Reserved 必须全部为零。

Literals_Lengths_Mode、Offsets_Mode 和 Match_Lengths_Mode 分别定义字面量长度代码、偏移量代码和匹配长度代码的 Compression_Mode。它们遵循相同的枚举:

Value (值)Compression_Mode (压缩模式)
0Predefined_Mode (预定义模式)
1RLE_Mode (RLE模式)
2FSE_Compressed_Mode (FSE压缩模式)
3Repeat_Mode (重复模式)

表 15: Literals_Lengths_Mode, Offsets_Mode, and Match_Lengths_Mode

Predefined_Mode (预定义模式) : 使用预定义的 FSE(参见第 4.1 节)分布表,如第 3.1.1.3.2.2 节中所定义。不会存在分布表。

RLE_Mode (RLE模式) : 表描述由一个字节组成,其中包含符号的值。此符号将用于所有序列。

FSE_Compressed_Mode (FSE压缩模式) : 标准 FSE 压缩。将存在分布表。此分布表的格式在第 4.1.1 节中描述。请注意,字面量长度代码和匹配长度代码表的最大允许精度日志为 9,偏移量代码表的最大精度日志为 8。当只有一个符号存在时,不得使用此模式;应改用 RLE_Mode(尽管任何其他模式也可以工作)。

Repeat_Mode (重复模式) : 将再次使用先前 Number_Of_Sequences > 0 的 Compressed_Block 中使用的表,或者如果这是第一个块,则使用字典中的表。请注意,这包括 RLE_Mode,因此如果 Repeat_Mode 跟随 RLE_Mode,则将重复相同的符号。它还包括 Predefined_Mode,在这种情况下,Repeat_Mode 将与 Predefined_Mode 具有相同的结果。不会存在分布表。如果在帧(或字典;参见第 5 节)中没有任何先前的序列表可重复的情况下使用此模式,则应将其视为损坏。

3.1.1.3.2.1.1. Sequence Codes for Lengths and Offsets (长度和偏移量的序列代码)

每个符号都是其自己上下文中的代码,它指定 Baseline(基线)和要添加的 Number_of_Bits(比特数)。代码经过 FSE 压缩,并在同一位流中与原始附加位交错。

字面量长度代码 (Literals Length Codes)

字面量长度代码是从 0 到 35(含)的值。它们定义从 0 到 131071 字节的长度。字面量长度等于解码的 Baseline 加上从位流中读取 Number_of_Bits 位的结果(作为小端值)。

Literals_Length_CodeBaselineNumber_of_Bits
0-15length0
16161
17181
18201
19221
20242
21282
22323
23403
24484
25646
261287
272568
285129
29102410
30204811
31409612
32819213
331638414
343276815
356553616

表 16: 字面量长度代码

匹配长度代码 (Match Length Codes)

匹配长度代码是从 0 到 52(含)的值。它们定义从 3 到 131074 字节的长度。匹配长度等于解码的 Baseline 加上从位流中读取 Number_of_Bits 位的结果(作为小端值)。

Match_Length_CodeBaselineNumber_of_Bits
0-31Match_Length_Code + 30
32351
33371
34391
35411
36432
37472
38513
39593
40674
41834
42995
431317
442598
455159
46102710
47205111
48409912
49819513
501638714
513277115
526553916

表 17: 匹配长度代码

偏移量代码 (Offset Codes)

偏移量代码是从 0 到 N 的值。

解码器可以自由限制其最大支持的 N 值。建议至少支持 22 的值。在撰写本文时,参考解码器支持的最大 N 值为 31。

偏移量代码也是以小端方式读取的附加位数,可以使用以下公式转换为 Offset_Value:

Offset_Value = (1 << offsetCode) + readNBits(offsetCode);
if (Offset_Value > 3) Offset = Offset_Value - 3;

这意味着最大 Offset_Value 为 (2^(N+1)) - 1,支持最多 (2^(N+1)) - 4 的后向引用距离,但受最大后向引用距离限制(参见第 3.1.1.1.2 节)。

从 1 到 3 的 Offset_Value 是特殊的:它们定义 "重复代码"。这在第 3.1.1.5 节中有更详细的描述。

3.1.1.3.2.2. Default Distributions (默认分布)

如果为符号类型选择了 Predefined_Mode,则其 FSE 解码表是从此处定义的预定义分布表生成的。有关如何将此分布转换为解码表的详细信息,请参见第 4.1 节。

3.1.1.3.2.2.1. Literals Length Codes (字面量长度代码)

解码表使用 6 位的精度日志(64 个状态)。

short literalsLength_defaultDistribution[36] =
{ 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
-1,-1,-1,-1
};

3.1.1.3.2.2.2. Match Length Codes (匹配长度代码)

解码表使用 6 位的精度日志(64 个状态)。

short matchLengths_defaultDistribution[53] =
{ 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
-1,-1,-1,-1,-1
};

3.1.1.3.2.2.3. Offset Codes (偏移量代码)

解码表使用 5 位的精度日志(32 个状态),支持最大 N 值为 28,允许最多 536,870,908 的偏移值。

如果压缩块中的任何序列需要比此更大的偏移量,则无法使用默认分布来表示它。

short offsetCodes_defaultDistribution[29] =
{ 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1
};