H.264裸码流(Raw Bitstream)数据主要由一系列的NALU(网络抽象层单元)组成。每个NALU包含一个NAL头和一个RBSP(原始字节序列载荷)。
H.264码流的结构可以分为两个层次:VCL(视频编码层)和NAL(网络抽象层)。下图为H.264码流中的层次图:
VCL层:负责对视频的原始数据进行压缩。VCL数据编码器直接输出的原始数据比特串(SODB),表示图像被压缩后的编码比特流。
NAL层:负责将VCL数据封装成NAL单元(NALU),并在网络上传输或存储到磁盘上。每个NAL单元之前需要添加StartCodePrefix,形成H.264码流。NAL层还处理拆包和组包的工作,以适应网络传输的最大传输单元(通常为1500字节)。
一个NALU由两个主要部分组成:
头部(Header):
NALU的头部包含了关于该单元的一些元数据信息,例如NAL单元类型(如序列参数集、图像参数集、帧数据单元等),NALU的优先级、参考帧标识、重要性指示等。头部的信息有助于解码器正确解析和处理每个NAL单元。
载荷(Payload):
NALU的载荷部分包含了实际的编码数据。这些数据可以是帧的视频数据、补充增强信息或其他特定于编码标准的数据。在视频解码过程中,解码器通过解析头部信息来识别NALU的类型,并且根据类型和载荷数据进行相应的解码和处理。
在H.264/AVC中,定义了多种NALU的类型,以适应不同的应用场景。常见的类型包括:
帧内预测(I)片:仅使用当前帧的信息进行编码。
预测(P)片:使用前一帧的信息进行编码。
双向预测(B)片:使用前一帧和后一帧的信息进行编码。
序列参数集(Sequence Parameter Set,SPS)包含了描述视频序列全局参数的信息,这些参数对于解码器正确解码视频流至关重要。以下是SPS的一些主要内容和结构:
SPS中的信息对于解码器初始化和正确解码视频流至关重要。如果SPS数据丢失或损坏,解码器可能无法正确解码视频。
图像参数集(Picture Parameter Set,PPS)包含了与单个图像编码相关的参数,这些参数用于控制图像的编码方式。以下是PPS的一些主要内容和结构:
PPS中的信息对于解码器正确解码视频流至关重要。PPS通常紧跟在SPS之后,并且可以有多个,因为不同的slice group可能有不同的参数设置。
AnnexB是一种常见的NALU(网络抽象层单元)封装格式,主要用于H.264和H.265视频编码标准。AnnexB格式的基本结构如下:
[开始代码] [NALU单元] [开始代码] [NALU单元] ...
每个NALU单元由一个开始代码和随后的原始字节数据组成,通过分隔符0x00 00 00 01或者0x00 00 01区分不同的NALU单元。如果在RBSP(原始字节流载荷)中出现了0x000000、0x000001、0x000002或0x000003这样的序列,就需要插入一个0x03字节来避免这些序列被误识别。例如,将0x000001变成0x00000301,这样在解码时可以去除0x03字节,恢复原始数据。这种方法确保了数据的完整性和正确解码。例如:
原始数据:0x000001
插入“模拟预防”字节后:0x00000301
解码时去除0x03字节,恢复为:0x000001
原始数据:0x000000
插入“模拟预防”字节后:0x00000300
解码时去除0x03字节,恢复为:0x000000
原始数据:0x000002
插入“模拟预防”字节后:0x00000302
解码时去除0x03字节,恢复为:0x000002
原始数据:0x000003
插入“模拟预防”字节后:0x00000303
解码时去除0x03字节,恢复为:0x000003
如果插入的数据本身包含了“模拟预防”字节(例如0x00000301),编码器会将其转义为0x0000030301。
AVCC(AVC Configuration)格式是一种用于存储和传输H.264视频流的格式,通常用于MP4、MKV等容器中。与Annex B格式不同,AVCC格式不使用起始码(start code)来分隔NALU(网络抽象层单元),而是使用NALU长度前缀。
AVCC格式结构:
假设有一个NALU数据为0x65 88 84 21
,其长度为4字节。在AVCC格式中,这个NALU会被存储为:
0x00 00 00 04 65 88 84 21
其中,0x00 00 00 04
表示NALU的长度为4字节,后面的65 88 84 21
是实际的NALU数据。
在解析AVCC格式时,需要先读取头部信息(extradata),然后根据NALU长度前缀来提取每个NALU的数据。
Annex B和AVCC是H.264视频编码中常见的两种NALU(网络抽象层单元)封装格式。它们各有优缺点,适用于不同的应用场景。以下是它们的优劣之处:
Annex B | |
---|---|
优点 | 简单直接:使用起始码(start code)0x000001 或0x00000001 来分隔NALU,便于解析和同步。广泛支持:许多硬件解码器和流媒体协议(如RTSP、RTP)默认支持Annex B格式。 实时流媒体:适合实时流媒体传输,因为起始码可以快速定位NALU的边界。 |
缺点 | 额外开销:起始码会增加一些额外的字节,导致数据冗余。 不适合文件存储:在文件存储中,起始码的存在可能会增加文件大小,不如AVCC格式高效。 |
AVCC | |
---|---|
优点 | 高效存储:使用NALU长度前缀(通常为4字节)来标识NALU的长度,减少了数据冗余,适合文件存储。 灵活性高:适用于多种容器格式(如MP4、MKV),便于在不同平台和设备之间传输和存储。 标准化:AVCC格式在许多多媒体框架和库(如FFmpeg、GStreamer)中得到广泛支持。 |
缺点 | 解析复杂:需要解析NALU长度前缀,增加了解码器的复杂性。 实时性较差:不如Annex B格式适合实时流媒体传输,因为需要额外的步骤来解析NALU长度。 |
选择建议
QP(Quantization Parameter,量化参数)是H.264视频编码中用于控制视频压缩的质量和比特率。QP值直接影响视频的量化步长(Qstep),从而影响视频的压缩程度和图像质量。QP值的作用:
QP值的范围,在H.264标准中,QP值的取值范围为0到51:
假设你有一个视频片段,使用不同的QP值进行编码:
QP值与量化步长(Qstep)之间存在一个对数关系。具体来说,QP每增加6,Qstep大约增加一倍。这个关系使得编码器可以在不同的QP值下灵活调整视频的压缩程度。
码率(Bitrate)是指单位时间内传输的数据量,通常以kbps(千比特每秒)或Mbps(兆比特每秒)为单位。码率在视频和音频编码中起着至关重要的作用,直接影响到文件的质量和大小。
码率的基本计算公式为:
码率 (kbps)=\frac{文件大小 (KB)×8}{时间 (秒)}
码率控制模式:
假设一个视频文件大小为500MB,时长为10分钟(600秒),其码率计算如下:
码率 (kbps)=\frac{500×1024×8}{600}≈6826.67 kbps
如何选择合适的码率?