

#### 音视频高手课07-视频流H264码流分析实战



#### 1.1 H.264编码格式



H.264的功能分为两层：

> - 视频编码层 
> - 网络提取层 

​		VCL数据即编码处理的输出，它表示被压缩编码后的视频数据序列。在VCL数据传输或存储之前，这些编码的VCL数据，先被映射或封装进NAL单元中。

​		每个**NAL单元**包括一个原始字节序列负荷（RBSP）、一组对应于**视频编码的NAL头信息**。

**RBSP的基本结构**是：在原始编码数据的后面填加了结尾比特。一个bit“1”若干比特“0”，以便字节对齐。

![img](img/68.png)

 

#### 1.2 H.264网络传输

​		H.264的编码视频序列包括一系列的**NAL单元**，每个NAL单元包含**一个RBSP**，

见表1。编码片（包括数据分割片IDR片）和序列RBSP结束符被定义为VCL NAL单元，其余为NAL单元。

​		**典型的RBSP单元序列如图2所示。**

每个单元都按独立的NAL单元传送。单元的信息头（一个字节）定义了RBSP单元的类型，NAL单元的其余部分为RBSP数据。

![img](img/69.png)

 

![img](img/70.png)

 

1. 2.1 **H.264码流结构图**     

![img](img/71.png)

  

起始码：如果NALU对应的Slice为一帧的开始，则用4字节表示，即0x00000001；否则用3字节表示，0x000001。 NAL Header：forbidden_bit，nal_reference_bit（优先级），nal_unit_type（类型）。 脱壳操作：为了使NALU主体不包括起始码，在编码时每遇到两个字节（连续）的0，就插入一字节0x03，以和起始码相区别。解码时，则将相应的0x03删除掉。

![img](img/72.png)

 

 H.264解码 **NAL头信息**的nal_referrence_idc（NRI）用于在重建过程中标记一个NAL单元的重要性，

1. 值为0表示这个NAL单元没有用预测，因此可以被解码器抛弃而不会有错误扩散；
2. 值高于0表示NAL单元要用于无漂移重构，且值越高，对此NAL单元丢失的影响越大。
3.  NAL头信息的隐藏比特位，在H.264编码器中默认为0，当网络识别到单元中存在比特错误时，可将其置为1。隐藏比特位主要用于适应不同种类的网络环境（比如有线无线相结合的环境）。     

![img](img/73.png)

 

NAL单元解码的流程为：首先从NAL单元中提取出RBSP语法结构，然后按照如图4所示的流程处理RBSP语法结构。输入的是NAL单元，输出结果是经过解码的当前图像的样值点。 NAL单元中分别包含了序列参数集和图像参数集。图像参数集和序列参数集在其他NAL单元传输过程中作为参考使用，在这些数据NAL单元的片头中，通过语法元素pic_parameter_set_id设置它们所使用的图像参数集编号；而相应的每个图像参数集中，通过语法元素seq_paramter_set_id设置他们使用的序列参数集编号。

几个例子：

![img](http://img.blog.csdn.net/20140720115202062?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbmNob25nXzIxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

 

 

3、 ffmpeg解析H264流程分析

这是一段实际的码流

![img](http://img.blog.csdn.net/20140720115512525?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbmNob25nXzIxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

 

  ffmpeg -i input.mp4 -vcodec h264 -preset fast -b:v 2000k hello.h264 

 