#此部分内容非常重要
先了解H264编解码相关的概念
1. H264的压缩比
- 如果采样YUV格式是4:2:0,分辨率是640 * 480, 帧率是15帧,那么YUV数据一秒的数据大小是52兆多一点;
- 针对上面的YUV参数H264建议的码流是500kbps,这个码流值是经验所得,那么压缩比就是 640 x 480 x 1.5 x 15 / 1024 / 500 约等于百分之一;
码流参考
2. GOP
- 就是一组强相关的视频帧,因为所以帧堆在一起,压缩很难处理,所以将视频帧进行分组后,再进行压缩。组内的视频内容是强相关的,比如做某一个动作,但是背景相同;
3. I/P/B帧
I帧也叫关键帧(intraframe frame),GOP组中的第一帧就是I帧。它是视频里最关键的帧,如果关键帧丢失后面的B/P帧视频数据就无法解析。
不依赖于任何参考帧,所以采用的是帧内压缩技术,就是自己编码,解码时也不需要其他参考帧。P帧(forward Predicted frame),向前参考帧。它依赖I帧,采用帧间压缩技术,也就是前面的帧必须解码完后,才能解码当前的P帧,因为P帧跟它前面的帧是密切相关的。
P帧的大小只有I帧的一半;B帧(Bidirectionally predicted frame),双向参考帧,它也依赖于I帧,也是采用帧间压缩技术。在解码时,它不仅参考前面的帧还要参考后面的帧,在一组帧数据中B帧是最后进行解码的,但是在播放的时候顺序是不会变的,会遵循IBP的顺序;
B帧占I帧的四分之一,虽然占用最小,但是解码时比较消耗CPU,也比较耗时,B帧越多延迟就会越大。因此不适合实时传播的场景;
B帧与B帧之间是没有参考的,也就是每一个B帧只参考前面的I或P帧和后面的P帧;IDR帧(Instantaneous Decoder Refresh)解码器立即刷新帧,它属于I帧,每个GOP中的第一帧就是IDR帧。因为IDR帧的作用是为了处理异常,防止错误传播,解码器每当遇到IDR时,就会清空解码器缓冲区中的所有内容。
-
SPS(Sequence Parameter Set)与PPS(Picture Parameter Set)
在每个IDR前面都有SPS和PPS帧,而且他们两个是一起出现的。- SPS是用来描述一组GOP的相关约束参数,如:id,帧数,参考帧数目,解码图像尺寸,帧场编码模式选择标识等;
-
相关重要参数
profile: 对视频压缩特性的描述,profile越高,就说明采用了越高级的压缩特性;
核心等级是Constrained baseline,从该核心等级中横向扩展除出了Baseline和Extend等级
纵向发展出了Main、High、High10、High422、Hight444,平时用的最多的就是Main等级
level:是对视频的描述,level越高,视频的码率、分辨率、帧率越高;
计算分辨率的相关参数:默认的宏块大小是16 x 16,如果计算宽度就 = (16 + 1) * pic_width_in_mbs_minus1; 如果有裁剪,再减去偏移量
```
pic_width_in_mbs_minus1 : 图像宽度包含的宏块个数 - 1
pic_height_in_mbs_minnus1 : 图像高度包含的宏块个数 - 1
frame_mbs_only_flag : 是帧编码还是场编码,前者是一行一行扫描,一整张图,后者是隔行扫描,会产生两张图,宽度不变,高度则是一张图的两倍
frame_cropping_flag : 图像是否需要裁减,如果需要裁减,通过下面4个参数进行操作
frame_crop_left_offset : 减去左侧的偏移量
frame_crop_right_offset : 减去右侧的偏移量
frame_crop_top_offset : 减去顶部的偏移量
frame_crop_bottom_offset : 底部的偏移量
```
获取gop中的帧数
log2_max_frame_num_minus4 表示2的次幂数,帧数就是2的^log2_max_frame_num_minus4次方,如果是0则表示是4;这个参数还能计算出被解码的帧的序号;
获取gop中的参考帧数
max_number_ref_frames
显示帧序号
pic_order_cnt_type 根据这个值计算帧的序号,有三个type,每个type的计算方式不一样,以后用到再补上;
帧率的计算
framerate = sps->vui.vui_time_scale / sps->vui.vui_num_units_in_stick / 2;
-
PPS是描述一组GOP中的每一幅图像的约束参数,如:id、熵编码选择标识、片数数目、初始量化参数、去方块滤波系数调整标识;
4. 帧与分组的关系
- 每个gop中都若干个B帧和P帧,但是只有一个I帧;
- 在解码时,先解码I帧,再解码P帧,最后再解码B帧。I自己就能解码,P帧依赖前面的I或P帧进行解码,B帧依赖前面I或P帧和后面I或P帧进行解码;
5. 宏块
- 是视频压缩操作时的一个基本单元,无论是帧内还是帧间压缩都是以宏块为操作单位;
- 将一张图像的分为若干个宏块,每个宏块都由具体个像素点组成,比如: 8 x 8,16 x 16。每个宏块还可以被划分为多个子宏块;
-
宏块越小,控制力就越强,压缩比越高,宏块越大,处理速度就越快;
H264的编解码流程
1. 关键帧编码
1. 选择帧内预测模式,计算每一个宏块适用的预测模式;
2. 根据预测数据和原图像做比较,得出每个宏块的残差值;
3. 将预测数据和残值数据进行转化量化,量化就是先DCT在CABAC;
4. 将数据封装成NAL包,进行数据分发;
2. 参考帧编码
1. 对参考帧和当前帧做运动评估【ME】;
2. 计算得出运动矢量【MC】;
3. 比较参考帧的和当前帧,得出残差值;
4. 将运动矢量得出的评估数据和残差值进行量化;
5. 将数据封装成NAL包,进行数据分发;
3. 解码流程
H264参考资料
x264编码器的功能最齐全
H264相关压缩技术
1. 有损压缩
帧内压缩技术
- 解决的是空域数据冗余问题,比如一张图像的很多个像素内容是相同的,就可以用很少的数据去表示它;
- 理论:
1、因为相邻像素差别不大,宏块的差别也不会很大,为了增加效率,所以以宏块为基础单位,对相邻宏块进行预测;
宏块在预测的时候,有9种预测模式,H264内部提供算法,会自动选择最接近的预判模式,推算出预测的宏块,预测的宏块会保存使用的预测模式,方便解码还原。
2、人的视力对亮度的敏感度比色度更高。所以在进行预测的时候颜色稍微有一些偏差,人眼很难察觉;
- 亮度块与色度块是分开进行预测的
- 预测出图像后,然后跟原图像进行比较,得出残差值,在压缩时将预测图像和残差值一起压缩;解码时就可以通过先得出预测图像,再和残差值进行比较,还原原图像;
帧间压缩技术
- 解决的是时域数据冗余问题,利用前一帧的数据进行压缩,帧与帧之间进行参考。
- 原理
1、在同一个GOP中进行帧间压缩,这是条件;
2、后面的帧参考前面的进行编码 ;
3、 运动估计,通过宏块匹配,得到运动矢量。
宏块匹配就是,在一组GOP中拿出两个相邻的帧,将前一个帧的宏块逐个与后一帧的图像中的宏块进行匹配,找到相似度非常高宏块然后记录坐标,算出运动矢量;
宏块匹配的算法有:三步搜索、二维对数搜索、四步搜索、钻石搜索;
4、运动补偿,就是找到残差值,方便解码时还原;
2. 无损压缩
- 在经过前两种压缩技术之后,再将空间上的相关性变为频域上无关的数据,最后进行量化;量化后有利于后面对数据进行无损压缩;
第1步:进行DCT变换(整数离散余弦变换),它的作用就是将分散的数据集中起来,因为经过有损压缩之后,数据在图表中的数据是分散的,不利于压缩,所以需要进行DCT变换,形成滤波,将所有分散的数据集中在某一角;
第2步:进行具体的无损压缩,有VLC和CABAC两种方式,后者压缩比更高;
VLC压缩(主要是MPEG2的无损压缩技术),也叫可变长的编码,用短的码代替出现频率高的码,用长的码代替出现频率低的码,这样高频码出现的越多,压缩率就越高;
CABAC(上下文适配的二进制算数编码),H264就采用这种无损压缩,随着时间的推移,根据上文下联系,使得压缩比更高;
H264的码流结构
H264的码流是进行分层存储的
1. NAL(Network Abstract Layer)层,
- 视频数据网络抽象层,处于数据的最外层,为了解决网络传输过程的丢包乱序问题,方便网络传输视频流;
2. VCL(Video Coding Layer)层,
-
视频数据编码层,被NAL层包裹,视频数据在经过有损压缩和无损压缩之后的数据就在这一层;
VCL的结构如下:
每一帧的图像由一个或多个slice组成,每个slice里面又存放的是多个宏块(MacroBlock)和一个头部,每个宏块又有多个子宏块,每个宏块里面存的有预测模式、预测数据、与原始图像宏块比较的残差值;
;
3. 码流基本概念
- SODB(String Of Data Bits),二进制数据串。
原始数据比特流,长度不是8的倍数,所以需要按8位进行补齐,由VCL层产生; - RBSP(Raw Byte Sequence Payload),按字节存储的原始数据;
就是将SODB的原始数据按照8位对齐的数据,如果缺三位就补一个1和两个0; - NALU (Network Abstrct Layer Unit), 网络抽象数据单元;
由一个字节的头部和RBSP组成,就是相当给RBSP套个头部方便数据识别; -
它们的关系用图描述如下:
-
码流分层总览图:
Annexb格式适用于将视频流保存成文件,前面要加个起始码;
RTP格式适用于将视频数据进行网络传输;
4. Slice 头部相关参数
- 帧类型,是I/P/B中的哪个类型帧;
- GOP中解码帧序号,如果GOP中有B帧就不是顺序解码了。
- 预测权重,在PPS中如果设置了预测权重,这个值才有值。
- 滤波,也跟PPS中的滤波参数控制有关。
问题分析
1. 视频花屏
- 是因为GOP分组中有P或B帧丢失了,造成了解码端的解码发生错误,就出现了马赛克;
2. 视频卡顿
- 这算是一种避免花屏的处理方案,就是在GOP分组中有帧丢失,就丢弃GOP内的所有帧,直到下一个关键帧IDR出现。因为I帧是按照周期来的,可能几百个帧才有一个关键帧出现(当然如果带宽或者业务要求,也可以几十帧插一个关键帧),这时在下一个关键帧到来的时候,屏幕是静止不动的;