目录:
- 前言
- H.264基本内容说明
- 结构分析
- 码流结构
最后推荐的文章很不错的~
前言:
官方介绍: H.264/AVC 项目的目的是为了创建一个比以前的视频压缩标准,在更低的比特率的情况下依然能够提供良好视频质量的标准(如,一半或者更少于MPEG-2,H.263,或者MPEG-4 Part2 ).同时,还要不会太大的增加设计的复杂性.
优势:
1.网络亲和性,即可适用于各种传输网络
2.高的视频压缩比,当初提出的指标是比 H.263,MPEG-4,约为它们的 2 倍,现在都已基本实现
那么很明显,什么时候需要到压缩呢?当然是文件体积太大的时候,所谓的视频,就是像小时候的连环画一样,在一秒内翻过 24 张以上的图片,就感觉图像是连续的了,这就是视频的原理.但是大家有没有想过,一张图片有多大呢?我们的屏幕分辨率按 1280 * 720 算,24fps的话,一秒钟的视频大概就 21.1 MB 了,大家想想,我们大部分的小伙伴为了下载个小嗨片省吃俭用才开了个 1M 的网线,然后连个直播都看不了是什么感觉.那肯定不能这样了,所以我们要进行压缩,而 H.264 不仅压缩比比较高,对网络的兼容性也非常好,所以大多数人做直播也就选择了 H.264 作为编码格式了.
H.264基本内容说明:
1. H.264编码的框架分两层
VCL(Video Coding Layer):负责高效的视频内容表示,VCL数据即被压缩编码后的视频数据序列.在VCL数据要封装到NAL单元中之后,才可以用来传输或存储.
NAL(Network Abstraction Layer):负责以网络所要求的恰当的方式对数据进行打包和传送
- SPS:序列参数集,作用于一系列连续的编码图像;
- PSS:图像参数集,作用于编码视频序列中一个或多个独立的图像;
参数集是一个独立的数据单位,不依赖于参数集外的其他句法元素。一个参数集不对应某一个特定的图像或序列,同一序列参数集可以被多个图像参数集引用,同理,同一个图像参数集也可以被多个图像引用。只在编码器认为需要更新参数集的内容时,才会发出新的参数集。
2. 重要变化
在H264中完全没有I帧、P帧、B帧、IDR帧的概念,之所以沿用这些说法是为了表明数据的编码模式.数据的组织形式从大到小排序是:序列(sequence)、图像(frame/field-picture)、片组(slice group)、片(slice)、宏块(macroblock)、块(block)、子块(sub-block)、像素(pixel).
3. 数据组织形式
片(slice):图像分成一帧(frame)或两场(field),而帧又可以分成一个或几个片(slice),片由宏块组成.宏块是编码处理的基本单元.一个slice编码之后被打包进一个NALU,NALU除了容纳slice还可以容纳其它数据,如SPS、PPS、SEI等
4. 编码相关术语
NALU:H264编码数据存储或传输的基本单元,一般H264码流最开始的两个NALU是SPS和PPS,第三个NALU是IDR.SPS、PPS、SEI这三种NALU不属于帧的范畴.
SPS(Sequence Parameter Sets):序列参数集,作用于一系列连续的编码图像.
PPS(Picture Parameter Set):图像参数集,作用于编码视频序列中一个或多个独立的图像.
SEI(Supplemental enhancement information):附加增强信息,包含了视频画面定时等信息,一般放在主编码图像数据之前,在某些应用中,它可以被省略掉.
IDR(Instantaneous Decoding Refresh):即时解码刷新
HRD(Hypothetical Reference Decoder):假想码流调度器
5. 帧编码模式
帧类型 | 描述 | 支持的框架 |
---|---|---|
I(Intra) | 只包含帧内预测的宏块(I) | 全部 |
P(Predicted) | 包含帧间预测宏块(P)和I型宏块 | 全部 |
B(Bi-Predictive) | 包含帧间双向预测宏块(B)和I型宏块 | 扩展和主 |
SP(Switching P) | 利于在编码的比特流中切换,包括I和P宏块 | 扩展 |
SI(Switching I) | 利用在编码的比特流中切换,包含SI宏块(一种特殊的帧内编码宏块) | 扩展 |
结构分析:
H.264 原始码流(又称为裸流),是有一个接一个的 NALU 组成的,而它的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer).
NAL 单元排列VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据 序列.在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中.每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息.RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特.一个 bit“1”若干比特“0”,以便字节对齐.
上图中的 NALU头 + RBSP 就相当与一个 NALU (Nal Unit), 每个单元都按独立的 NALU 传送. 其实说白了,H.264 中的结构全部都是以 NALU 为主的,理解了 NALU,就理解 H.264 的结构了.
一帧图片跟 NALU 的关联:
一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了,我们可以来看看 NALU 跟片的关系(slice).
图片编码后
NALU 结构
小伙伴们要明白,片(slice)的概念不同与帧(frame),帧(frame)是用作描述一张图片的,一帧(frame)对应一张图片,而片(slice),是 H.264 中提出的新概念,是通过编码图片后切分通过高效的方式整合出来的概念,一张图片至少有一个或多个片(slice).
上图中可以看出,片(slice)都是由 NALU 装载并进行网络传输的,但是这并不代表 NALU 内就一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息.
什么是切片(slice)?
片的主要作用是用作宏块的载体(ps:下面会介绍到宏块的概念).片之所以被创造出来,主要目的是为限制误码的扩散和传输.
如何限制误码的扩散和传输?
每个片都应该是互相独立被传输的,某片的预测(片内预测和片间预测)不能以其它片中的宏块为参考图像.
那么片(slice)的具体结构,我们用一张图来直观说明吧:
slice结构
我们可以理解为一 张/帧 图片可以包含一个或多个分片(Slice),而每一个分片(Slice)包含整数个宏块(Macroblock),即每片(slice)至少一个 宏块(Macroblock),最多时每片包含整个图像的宏块.
上图结构中,我们不难看出,每个分片也包含着头和数据两部分:
1、分片头中包含着分片类型、分片中的宏块类型、分片帧的数量、分片属于那个图像以及对应的帧的设置和参数等信息.
2、分片数据中则是宏块,这里就是我们要找的存储像素数据的地方.
什么是宏块?
宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息.视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列.
组成部分:一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成.每个图象中,若干宏块被排列成片的形式.
我们先来看看宏块的结构图:
宏块结构图
从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度数据集等等信息.
切片(slice)类型跟宏块类型的关系
对于切片(slice)来讲,分为以下几种类型:
- I片: 只包 I宏块,I 宏块利用从当前片中已解码的像素作为参考进行帧内预测(不能取其它片中的已解码像素作为参考进行帧内预测).
- P片: 可包 P和I宏块,P 宏块利用前面已编码图象作为参考图象进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即 16×16、16×8、8×16 或 8×8 亮度像素块(以及附带的彩色像素);如果选了 8×8 的子宏块,则可再分成各种子宏块的分割,其尺寸为 8×8、8×4、4×8 或 4×4 亮度像素块(以及附带的彩色像素).
- B片: 可包 B和I宏块,B 宏块则利用双向的参考图象(当前和 来的已编码图象帧)进行帧内预测.
- SP片(切换P): 用于不同编码流之间的切换,包含 P 和/或 I 宏块
- SI片: 扩展档次中必须具有的切换,它包 了一种特殊类型的编码宏块,叫做 SI 宏块,SI 也是扩展档次中的必备功能.
整体结构
通过剖析了这么多个小零件,是时候个大家一个世界地图了,
那么我们的 NALU 整体结构可以呼之欲出了,以下就引用 H.264 文档当中的一幅图了
其实 H.264 的码流结构并没有大家想的那么复杂,编码后视频的每一组图像(GOP,图像组)都给予了传输中的序列(PPS)和本身这个帧的图像参数(SPS),所以,我们的整体结构,应该如此:
GOP (图像组)主要用作是形容一个 i 帧 到下一个 i 帧之间的间隔了多少个帧,增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了.