上一章介绍了H.264帧间编码原理,本章开始介绍H.264码流组成
组成H.264码流的结构主要包含以下几个部分,从大到小排序一次是:H.264视频序列、GOP、图像、片组(slice集合)、片(slice)、NALU、宏块、像素。
H.264视频序列:一段视频
GOP:从I帧到下一个I帧之间的内容
图像:视频中的一帧
片组(slice集合):片的集合
片(slice):一大块像素数据
NALU:00 00 00 01 或 00 00 01标志一个NALU单元的开始
宏块:被信源编码器划分出来的一个区域,是编码处理的基本单元
像素:一个像素数据
NAL类型:
在一段H.264数据中,如果NALU对应的slice为一帧的开始,则起始码分隔符用4个字节表示,即00 00 00 01,否则用3个字节表示,即00 00 01。
注:为了使NALU主体中不包括起始码,在编码时每遇到两个连续字节的0,就插入一个字节0x03,以和起始码相区别,解码时,则将相应的0x03删除掉。
NAL有以下32种类型:
nal_unit_type | NAL类型 |
0 | 未使用 |
1 | 不分区、非IDR图像的片 |
2 | 片分区A |
3 | 片分区B |
4 | 片分区C |
5 | IDR图像中的片(slice),即I帧 |
6 | 补充增强信息单元(SEI) |
7 | 序列参数集(sps) |
8 | 图像参数集(pps) |
9 | 分界符 |
10 | 序列结束 |
11 | 码流结束 |
12 | 填充 |
13-23 | 保留 |
24-31 | 未使用 |
下面以一段h.264码流数据为例,使用分析工具打开
通过以上码流数据可以看出,在起始码后面出现的第一个数字是67,对照上面NAL的类型表发现,67已经远远大于了其中的32种类型的值,那么怎么知道是那种类型呢?
我们使用计算器将十六进制数67转化为二进制,即:0110 0111,如下图:
事实上,真正存储NAL类型的是其二进制的后5位,可以通过&后5位的值得到真实的类型,即二进制0001 1111即可,转换成16进制就是1F,如下图:
0110 0111 & 0001 1111 结果为0 0111,转成十进制就是7,即序列参数集(sps)
同样的,根据分隔符继续往后找,可以找到00 00 00 01 68,同样使用以上方式0x68 & 0x1F = 8,即图像参数集(pps)
以此类推。。。
哥伦布编解码:
百度了一下网上的博客,解释哥伦布编解码都比较复杂,这里尽可能简单的解释一下
我们知道,一个字节是由8个bit位组成,比如十进制:4,用二进制表示就是:0000 0100
编码:
以上面的4为例
1. 根据哥伦布编码规则,需要再原数据的基础上加1,得到二进制101;
2. 从左往右开始找二进制的第一个1,然后看1后面还有多少位,可以看到,1后面还有0和1两位,根据哥伦布编码规则,需要在第一个1的前面加上几个0,则得到:00101
3. 至此,哥伦布编码结束,得到最终值:00101
解码:
以上面编码完成的00101为例
1. 根据哥伦布解码规则,从左往右开始数0,直到遇到第一个1,统计1前面0的个数,这个可以看到,第一个1前面有2个零,记录下来
2. 根据步骤1.得到的统计的0的个数,从第一个1后面继续往后数统计的0个数位,也就是往后数2位,得到01,加上前面的1,得到值:101
3. 根据哥伦布解码规则,需要在得到的数值上减去1,得到100,转换成十进制就是:4
4.至此,哥伦布解码结束,得到原始值:4
获取视频的宽高:
在获取视频宽高前,先通过对sps码流的分析,进而直到获取到宽高
SPS码流解析:
有了以上的理论基础,接下来我们来分析一段码流数据的内部原理,我将上图中的sps数据拷贝下来了,数据如下:
00 00 00 01 67 64 00 15 AC D9 41 70 C6 84 00 00 03 00 04 00 00 03 00 F0 3C 58 B6 58
这里我们通过位来分析,首先索引初始值位0,前面4个字节00 00 00 01是分割符不做分析,此时索引值跳到了4个字节 * 每个字节8位 = 32位这里,那么索引就从32开始
字节索引值 | 字节内容 | 二进制 | 位索引值 | 位内容 | 解码方式 | 解码为10进制 | 位含义 |
0-3 | 00 00 00 01 | 不做分析 | 0-31 | 不做分析 | |||
4 | 67 | 0110 0111 | 32 | 0 | 直接取值 | 0 | |
33-34 | 11 | 直接取值 | 3 | ||||
35-39 | 00111 | 直接取值 | 7 | nal_unit_type(帧类型) | |||
5 | 64 | 0110 0100 | 40-47 | 0110 0100 | 直接取值 | 100 | profile_idc(编码等级) |
6 | 00 | 0000 0000 | 48 | 0 | 直接取值 | 0 | constrained_set0_flag( 值为1时:码流应遵循基线Baseline profile的所有约束 值为0时:) |
49 | 0 | 直接取值 | 0 | constrained_set1_flag( 值为1时:码流应遵循Main profile的所有约束) | |||
50 | 0 | 直接取值 | 0 | constrained_set2_flag( 值为1时:码流应遵循Extended profile的所有约束) | |||
51 | 0 | 直接取值 | 0 | constrained_set3_flag( 当constrained_set0_flag,constrained_set1_flag,constrained_set2_flag中不只一个值为1的话,码流必须满足) | |||
52-55 | 0000 | 直接取值 | 0 | 4个零位对齐 | |||
7 | 15 | 0001 0101 | 56-63 | 0001 0101 | 直接取值 | 21 | level_idc(码流等级) |
8 | AC | 1010 1100 | - | 1 | 哥伦布 | 0 | seq_parameter_set_id(取值为0-31,表示当前的序列参数集的id,图像参数集pps可以引用其代表的sps中的参数) |
- | 010 | 哥伦布 | 1 | chroma_format_idc(取值为0-3,表示采样 如单色yuv420 yuv422 yuv444)[受profile_idc影响, profile_idc 为100 110 122 144] | |||
- | - | 直接取值 | - | residual_colour_transform_flag(取值为0-1,残差颜色变换标志,等于0时不使用残余颜色变换,等于1时要使用残差变换,受chroma_format_idc影响,chroma_format_idc为3) | |||
- | 1 | 哥伦布 | 0 | bit_depth_luma_minus8(取值0-4,视频亮度位深 0 High 只支持8bit 1 High10 支持10bit)[受profile_idc影响,profile_idc 为100 110 122 144] | |||
- | 1 | 哥伦布 | 0 | bit_depth_chroma_minus8(取值0-4,视频色度位深 )[受profile_idc影响,profile_idc 为100 110 122 144] | |||
- | 0 | 直接取值 | 0 | qpprime_y_zero_transform_bypass_flag(取值0-1,0 变换系数解码过程和图像构建过程在去块效应滤波过程之前执行而不使用变换旁路操作,1 变换系数解码过程的变换旁路操作和图像构建过程将会在H264文档第8.5节给出的去块效应滤波过程之前执行)[受profile_idc影响,profile_idc 为100 110 122 144] | |||
- | 0 | 直接取值 | 0 | seq_scaling_matrix_present_flag(缩放矩阵标志位)[受profile_idc影响,profile_idc 为100 110 122 144] | |||
- | - | 直接取值 | - | [受seq_scaling_matrix_present_flag影响,seq_scaling_matrix_present_flag不为0时,取8位] | |||
9 | D9 | 1101 1001 | - | 1 | 哥伦布 | 0 | log2_max_frame_num_minus4(最大帧率) |
- | 1 | 哥伦布 | 0 | pic_order_cnt_type(指明了poc(picture order count)的编码方法,poc标识图像的播放顺序,确定播放顺序和解码顺序的映射) | |||
- | 011 | 哥伦布 | 2 | log2_max_pic_order_cnt_lsb_minus4(指明了变量MaxPicOrderCntLsb的值)[受pic_order_cnt_type影响,pic_order_cnt_type为0] | |||
- | - | 直接取值 | - | delta_picorder_always_zero_flag(delta pic顺序始终为零标志)[受pic_order_cnt_type影响,pic_order_cnt_type为1] | |||
- | - | 哥伦布 | - | offset_for_nonred_pic[受pic_order_cnt_type影响,pic_order_cnt_type为1] | |||
- | - | 哥伦布 | - | offset_for_top_to_buttom_field[受pic_order_cnt_type影响,pic_order_cnt_type为1] | |||
- | - | 哥伦布 | - | num_ref_frames_in_pic_order_cnt_cycle[受pic_order_cnt_type影响,pic_order_cnt_type为1] | |||
- | - | 哥伦布 | - | offset_for_ref_frame[循环num_ref_frames_in_pic_order_cnt_cycle值的次数][受pic_order_cnt_type影响,pic_order_cnt_type为1] | |||
- | 00101 | 哥伦布 | 4 | max_num_ref_frames(指定参考帧队列可达到的最大长度,最大帧数) | |||
10 | 41 | 0100 0001 | - | ||||
- | 0 | 直接取值 | 0 | gaps_in_frame_num_values_allowed_flag( 值为1时,表示句法元素frame_num可以不连续,允许丢弃若干帧) | |||
- | 000010111 | 哥伦布 | 22 | 视频宽度(需+1(原理:如果视频的宽就是16,那么在码流中就只需要存一个1就可以了)后乘以最大宏块像素数,也就是 (22+1) * 16 = 368) | |||
11 | 70 | 0111 0000 | - | ||||
- | 000011000 | 哥伦布 | 23 | 视频高度(需+1(原理:如果视频的高就是16,那么在码流中就只需要存一个1就可以了)后乘以最大宏块像素数,也就是 (23+1) * 16 = 384) | |||
12 | C6 | 1100 0110 | - |
profile_idc:编码等级
profile_idc值 | 含义场景 |
66 | Baseline(直播) |
77 | Main(一般场景) |
88 | Extende |
100 | High(FRExt) |
110 | High 10(FRExt) |
122 | High 4:2:2(FRExt) |
144 | HIgh 4:4:4(FRExt) |
level_idc:码流等级(某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定)
level_idc值 | 级别含义 |
10 | 1(380160 samples/sec) |
11 | 1.1(768000 samples/sec) |
12 | 1.2(1536000 samples/sec) |
13 | 1.3(3041280 samples/sec) |
20 | 2(3041280 samples/sec) |
21 | 2.1(5068800 samples/sec) |
22 | 2.2(5184000 samples/sec) |
30 | 3(10368000 samples/sec) |
31 | 3.1(27648000 samples/sec) |
32 | 3.2(55296000 samples/sec) |
40 | 4(62914560 samples/sec) |
41 | 4.1(62914560 samples/sec) |
42 | 4.2(125829120 samples/sec) |
50 | 5(150994944 samples/sec) |
51 | 5.1(251658240 samples/sec) |
chroma_format_idc:与亮度取样对应的色度取样
chroma_format_idc值 | 色彩格式 | SubWidthC | SubHeightC |
0 | 单色 | - | - |
1 | 4:2:0 | 2 | 2 |
2 | 4:2:2 | 2 | 1 |
3 | 4:4:4 | 1 | 1 |