一、为什么要对视频编码
视频是由一帧帧的图像组成,就像gif图片一样。一般视频为了不会让人感觉到卡顿,一秒钟至少需要16帧画面(一般30帧)。加入该视频是一个1280x720的分辨率,那么不经过编码一秒钟传输的大小为1280x720x60~=843M。所以不经过编码的视频根本没法保存和传输。现在市面上主要将编码分为两大类H.264和MPEG。后面一种主要用于DVD,机顶盒等设备。h264编码是一种主流的编码格式。另外H265也属于其中的一种,比如我们电影院播放的电影,一些高清的电视采用的就是这种编码技术。
二、H264编码规则
在相邻的几幅画面中,一般有差别的像素是10%以内的点,亮度差值变化不超过20%,而色度差值的变化只有不到1%,所以对于一段变化不大的画面,我们可以先编码成一个完整的图片帧A
随后的B帧就不编码全部图像,只写入A帧的差别,这样B帧的大小只有完整帧大小的10%或者更小!B帧之后的C帧如果变化不大,我们可以继续以参考B帧的方式进行编码,依次循环下去。
这段图像我们称之为一个序列:序列就是有相同特点的一段数据。当某个图像与之前的图像变化很大,无法根据前面的帧来生成,我们就结束上一段序列,开启下一段序列,也就是对这个图像生成完整的帧A1,随后的帧将参考A1帧,只写入与A1差别的内容。这个序列就是Gop序列,我们也可以把它当作一个场景,比如场景A和场景B,场景A的背景是红色,场景B的背景是绿色,那么A和B就是两个序列。每个序列是从I帧开始的,并且是唯一的,后面是B帧和P帧。两个I帧之间就是一个序列
三、H264编码
I帧、P帧、B帧是如何生成的呢?前面说过,当两个场景差异很大的时候,就会重新开始一个序列,那么这个序列就是从I帧开始的,也称关键帧。那么与I帧相似度极高,到达95%以上,则被编码成B帧;相似度达到70%编码为P帧。I、P、B帧的如何编码不需要我们自己实现,x264工具就已经帮我们完成了。
前面已经说过编码的目的就是为了方便传输(指文件传输,网络流传输等)。但是我们并不能把一帧帧传过去,一帧的内容几十k也是太大了,还需要细分才能更好的传输,所以我们需要更小的传输单元,保证更高的压缩性、容错性以及实时观看性。那么就引入了NALU单元
四、NALU单元
上图可以看到,一帧数据(一张图片)是由很多个NALU单元组成,一个NALU单元分为两部分:NAL头和RBSP
1、NAL头:标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元
0:未规定
1:非IDR图像中不采用数据划分的片段
2:非IDR图像中A类数据划分片段
3:非IDR图像中B类数据划分片段
4:非IDR图像中C类数据划分片段
5:IDR图像的片段
6:补充增强信息(SEI)
7:序列参数集(SPS)
8:图像参数集(PPS)
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13:序列参数集扩展
14:带前缀的NAL单元
15:子序列参数集
16 – 18:保留
19:不采用数据划分的辅助编码图像片段
20:编码片段扩展
21 – 23:保留
24 – 31:未规定
2、RBSP:又被成为切片,每个切片是由片头和片数据组成,片数据是由若干个宏块组成。包括序列参数集 SPS 和 图像参数集 PPS
3、SPS与PPS
概念:包含了初始化H.264编码所需要的信息参数。包括编码所用的profile,level,图片的宽和高,deblock滤波器等
SPS:序列参数集,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识 等等。
PPS:图像参数集,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等。
在H.264编码中都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"为开始码的,找到开始码后,使用开始码后的第一个字节的低5位判断是否为7(sps)或8(pps),即data[4]&0x1f==7或data[4]&0x1f==8。然后对获取的nal去掉开始码之后进行base64编码,得到的信息就可以用于sdp,sps,pps,需要用逗号隔开。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)