H2.64和H2.65编码区别
AAC音频格式ADTS头详解
RTP载荷H264(实战细节)
RTP载荷H265(实战细节)
NALU:
h264编码数据存储和传输的基本单元,也就是说好64的编码数据无论是存储还是传输都是由一个一个的NALU单元组成的。
h264码流格式:
H264码流格式图
1. NALU单元一个接一个怎么区分哪个是哪个呢?
每个NALU单元前都会使用四字节0x00000001/0x000001分隔NALU。
例如:
00 00 00 01 SPS 00 00 00 01 PPS 00 00 00 01 I帧 00 00 00 01 P帧
当然上面的例子是基于I帧 p帧都只有一个NALU的情况,根据上面的 “H264码流格式图”可以看出有可能I帧,p帧数据比较大占用了多个NALU,这种情况如下:
00 00 00 01 SPS 00 00 00 01 PPS 00 00 00 01 I帧NALU 00 00 01 I帧NALU 00 00 00 01 P帧
由上面的数据可以看出,一帧可能分为很多个NALU,只有第一个NALU的起始码为0x00000001,后面的NALU的起始码为0x000001.
2. 一帧数据占用了多个NALU,那么怎么区分一个NALU到底属于SPS PPS I帧等中的哪一个呢?
每个NALU以00000001/0x000001分割后的下一个字节就记录着该NALU的类型,NALU的格式如下:
起始码 | 类型 | 数据 | 下个NALU |
00 00 00 01 | 1字节 | N字节负荷 | 00 00 00 01 |
1字节类型的协议为:
1bit禁止位 | 2bit重要指示位 | 5bit 类型 |
固定为0 | 11 | NALU类型,具体参考NALU类型表 |
NALU类型对照表:
0x67 (0 11 00111) | SPS | 非常重要 | type = 7 |
0x68 (0 11 01000) | PPS | 非常重要 | type = 8 |
0x65 (0 11 00101) | IDR帧 | 关键帧 非常重要 | type = 5 |
0x61 (0 11 00001) | I帧 | 重要 | type=1非IDR的I帧不大常见 |
0x41 (0 10 00001) | P帧 | 重要 | type = 1 |
0x01 (0 00 00001) | B帧 | 不重要 | type = 1 |
0x06 (0 00 00110) | SEI | 不重要 | type = 6 |
NALU类型的详细解析表:
nal_unit_type | NAL单元和RBSP语法结构的内容 |
0 | 未指定 |
1 | 一个非 IDR 图像的编码条带(p帧/b帧) |
2 | 编码条带数据分割块 A |
3 | 编码条带数据分割块 B |
4 | 编码条带数据分割块 C |
5 | IDR 图像的编码条带(IDR帧) |
6 | 辅助增强信息 (SEI) |
7 | 序列参数集 |
8 | 图像参数集 |
9 | 访问单元分隔符 |
10 | 序列结尾 |
11 | 流结尾 |
12 | 填充数据 |
13 | 序列参数集扩展 |
14-18 | 保留 |
19 | 未分割的辅助编码图像的编码条带 |
20-23 | 保留 |
24-31 | 未指定 |
可以看出只通过NALU的类型是判断不出I帧 p帧 b帧的,需要到slice层去判断用到“熵编码”。
SPS:
序列参数集,保存一组编码序列的全局参数。
PPS:
图像参数集, 保存一帧数据的全部参数。
SEI:
辅助增强信息,主要起辅助增强的作用。
GOP:
图像组,主要形容一个IDR帧到下一个IDR帧之间有多少帧数据。在解码过程中,当出现了IDR帧时,要更新sps、pps,原因是防止前面I帧错误,导致sps,pps参考I帧导致无法纠正。
IDR帧:
GOP的第一个I帧,一个GOP可能有很多I帧,所以IDR帧是I帧,I帧不一定是IDR帧。
时间戳:
DTS:
解码时间戳,决定这个压缩包数据什么时候解码。存在于编码后或者解码前的数据。
PTS:
显示时间戳,决定原始帧什么时候显示给用户。存在于解码后或者编码前的数据。