单纯传输视频画面,视频量很是大,对现有的网络和存储来讲是不可接受的。html
为了可以使视频便于传输和存储,人们发现视频有大量重复的信息,若是将重复信息在发送端去掉,在接收端恢复出来,这样就大大减小了视频数据的文件,所以有了H.264视频压缩标准。算法
又称为关键帧或者帧内编码帧,采用帧内压缩技术。缓存
是一种自带所有信息的独立帧,无需参考其余图像即可独立进行解码,能够简单理解为一张静态画面。视频序列中的第一个帧始终都是I帧,由于它是关键帧。bash
又称为
向前参考帧
或帧间预测编码帧
,采用帧间压缩技术。网络
除了I帧
以外的全部帧,所有向前依赖。性能
全部帧都只保存与前一帧的差别,以达到高压缩率的效果。编码
解码时须要用以前缓存的画面叠加上本帧定义的差异,生成最终画面。spa
又称为刷
双向参考帧
,属于帧间压缩技术。.net
即参考前一帧,也参考后一帧。以达到比P帧
更高的压缩效果。3d
也就是说要解码B帧,不只要取得以前的缓存画面,还要解码以后的画面,经过先后画面的与本帧数据的叠加取得最终的画面。对于直播业务,B帧比P帧永远要慢一点。
B帧压缩率高,可是对解码性能要求较高。
I帧只需考虑本帧
P帧记录的是与前一帧的差异
B帧记录的是前一帧及后一帧的差异
能节约更多的空间,视频文件小了,但相对来讲解码的时候就比较麻烦。
由于在解码时,不只要用以前缓存的画面,并且要知道下一个I或者P的画面,对于不支持B帧解码的播放器容易卡顿。
复制代码
视频监控系统中预览的视频画面是实时的,对画面的流畅性要求较高。采用I帧、P帧进行视频传输能够提升网络的适应能力,且能下降解码成本因此现阶段的视频解码都只采用I帧和P帧进行传输。
Group of Pictures 一组帧
类似画面的一组帧
以下图所示,两个I帧
之间的全部帧,叫作一组帧。
具体的划分细节,在下面《帧分组》的部分会提到
序列参数集 Sequence Parameter Set
包含一组帧中:存放帧数、参考帧数目、解码图像尺寸、帧场编码模式选择标识等
图像参数集 Picture Parameter Set
包含一组帧中:存放熵编码选择模式标识、片组数目、初始量化参数和去方块过滤波系数调整标识等
在一组帧中,SPS与PPS也属于I帧。
当一组帧中丢失了某一帧,就会形成某个部分没有完成更新。形成花屏。
为了不花屏的问题,当发现I帧或P帧丢失,则不现实本GOP中全部的内容。知道下一个I帧到达后从新刷新图像。
x264是目前使用最普遍的H264编解码器(主要用来编码,解码用ffmpeg)。 x265的压缩率比x264更高,性能的消耗也更大。
相对x264性能较低,但支持SVC技术。
SVC能够将视频分层传输:
能够对用户带宽进行不一样策略的定制方案:将一帧数据分为小、中、大三个部分,根据对方网络状况分别追加发送。
接收到的部分越多,最后组合起来的视频就越清晰。
但因为不少手机不支持SVC编码,因此须要使用软编处理,会对CPU产生损耗。
Google出品,分别对应x264/x265
这部分最后发现李超老师本身已经写过博客了,建议去看原文
解决空域数据的冗余问题
空域数据,相似音频中的超声波段,不容易甚至不会被人类注意识别。
解决时域数据的冗余问题
时域数据,对于监控之类静止不动的画面,对帧与帧之间重复的数据进行计算压缩。
将空间上的相关性变为频域上无关的数据而后进行量化
相似哈夫曼无损编码
对于一段视频,首先会被送到 H264 编码器的缓冲区中,并为每一帧图片进行宏块的划分
H264默认是使用 16X16 大小的区域做为一个宏块,也能够划分红 8X8 大小。
对宏块中的每个像素点进行计算
对于复杂的图片或局部,H264能够对宏块进行更细致的划分以达到更高的压缩率,好比8X16、 16X8、 8X8、 4X8、 8X4、 4X4
宏块划分好后,还须要对编码器缓存中全部的图片进行分组(GOP)
帧间预测压缩
主要在这里解决时域数据的冗余问题
:
对于某些关联特别密切的帧,其实咱们只须要保存一帧的数据,其它帧均可以经过这一帧再按某种规则预测出来,因此说视频数据在时间上的冗余是最多的。
如何断定两帧处在一个GOP中?以一个的台球桌的视频为例:
H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的类似度。以下图:
其算法是:在相邻几幅图像画面中,通常有差异的像素只有10%之内的点,亮度差值变化不超过2%,而色度差值的变化只有1%之内,咱们认为这样的图能够分到一组。
也叫
运动估计与补偿
,用于压缩时间层面的冗余,清除相同数据。
对于一组帧,须要计算运动物体的运动矢量:
H264编码器首先按顺序从缓冲区头部取出两帧视频数据,而后进行宏块扫描。当发现其中一幅图片中有物体时,就在另外一幅图的邻近位置(搜索窗口中)进行搜索。若是此时在另外一幅图中找到该物体,那么就能够计算出物体的运动矢量了。
下面这幅图就是搜索后的台球移动的位置
H264依次把每一帧中球移动的距离和方向都记录下来就成了下面的样子
运动矢量计算出来后,将相同部分(也就是绿色部分)减去,就获得了补偿数据。咱们最终只须要将补偿数据进行压缩保存,之后在解码时就能够恢复原图了。压缩补偿后的数据只须要记录不多的一点数据。以下所示
人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感。因此基于一些研究,能够将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。
H264的帧内压缩与JPEG很类似。一幅图像被划分好宏块后,对每一个宏块能够进行 9 种预测模式
。找出与原图最接近的一种预测模式。帧内预测后的图像与原始图像的对好比下:
将预测图像与原图像对比获得残差值
,解码时根据记录下来的预测模式
与残差值
,便可还原出本来的图像。
能够将
残差值
作整数离散余弦变换
,去掉数据的相关性,进一步压缩数据。
好比:
压缩后变成
根据信息出现的频率,对总体进行压缩
参考哈夫曼编码:对高频信息使用短码,而低频信息使用长码进行压缩。
MPEG-2
中使用的VLC
就是这种算法
而在H264中,使用CABAC
进行压缩,不仅对频率进行压缩,还根据上下文进行进一步压缩
对于视频帧,在有了上下文以后,剩下的帧会进一步压缩
从大到小,H264的视频结构以下所示 视频流 => N个视频帧 => N个切片 => 切片头+N个宏块 => N个子块
网络抽象层 以太网单个数据包限制为1500字节,NAL能够将单帧数据进行拆包与组包处理,以进行传输。
视频编码层 对视频的原始数据进行压缩
原始数据比特流
由NAL层产生。长度不必定是8字节的倍数
为
SODB
末尾补1,而后补零成8位。
起始标记的格式化
在
EBSP
前加一个1B的网络头
NALU 头部信息,由三部分构成
对于Type(nal_unit_type):
1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其余类型的NAL单元为非VCL的NAL单元。
0:未规定
1:非IDR图像中不采用数据划分的片断
2:非IDR图像中A类数据划分片断
3:非IDR图像中B类数据划分片断
4:非IDR图像中C类数据划分片断
5:IDR图像的片断
IDR帧属于I帧,此位置表明关键帧的一部分
6:补充加强信息 (SEI)
7:序列参数集/SPS
8:集图像参数/PPS
SPS和PPS都是特殊的NALU。一个MP4文件只有一个SPS,可是有不少PPS,SPS必须在全部NALU的最开头。
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13 – 23:保留
24 – 31:未规定 (2七、28表示为分片NALU)
复制代码
一个RTP数据包中只包含一个NALU(切片)
不少P帧、B帧都是单一类型
一个RTP数据包中包含多个NALU
好比SPS、PPS一般就会放在同一个RTP数据包内进行发送
一个NALU被分片成多个RTP数据包发送
红、绿、蓝。每一个元素1字节,共24位
从电视系统中衍生出来的一套颜色编码方式
明亮度(灰阶值)。基础信号,非黑即白
色彩和饱和度。用于指定像素颜色
YUV常见格式能够参阅:YUV格式介绍
其中最多见的是YUV 4:2:0
,相对RGB 8:8:8
的格式,节省了不少空间。
YUV 4:2:0
并不意味着没有V份量,而是只在相邻的分行扫描中一行采用YUV 4:2:0
,下一行采用YUV 4:0:2
这种抽样存储。
能够参阅视频存储格式YUV420 NV12 NV21 i420 YV12