FFMPEG之H264理论篇02

FFMPEG之H264理论篇02

前言

由于刚接触音视频行业,需要去对视频进行编解码,所以这几天就去看了H264相关的博客和视频,当然少不了雷神的博客,但是雷神的博客理论部分几乎没有说,而且大部分人的博客都是讲得非常混乱的,很难去分析对与错。本来想拿几天搞掂,结果自己一查,才知道要想吃透H264根本没有那么简单,所以这里只是深入研究到RBSP部分,剩下的片、宏块、子块以及熵编码、哥伦布编码等等具体的只能先放着了,因为上班也没有太多时间给你研究。

1 H263与H264的分层结构

H.263 定义的码流结构是分级结构,共四层。自上而下分别为:图像层(picturelayer)、块组层(GOB layer)、宏块层(macroblock layer)和块层(block layer)。
例如NALU就是图像层,保存着视频的每一帧,一般前两个NALU即前两帧是SPS和PPS类型的NALU,第三个有可能是I帧类型的NALU(nalu_type=5,下面会讲到),后面基本是IDR片(nalu_type=1)的NALU;而块组层GOB也就是我们的片,你可以认为它是存储一个或多个切片的东西,有I、B、P片;宏块就是将某一帧分割成多个8x8或者16x16的正方形;块层即子块当然是宏块的单位,保存着宏块的类型、宏块预测的数据以及残差数据等等。

而与H.263相比,H.264 的码流结构和H.263的有很大的区别,它采用的不再是严格的分级结构。
H.264 的功能分为两层:视频编码层(VCL, Video CodingLayer)和网络抽象(提取)层(NAL, Network Abstraction Layer)。VCL表示压缩编码后的视频数据序列。在VCL数据传输或存储之前,VCL 数据在NAL层加工被封装进NAL单元中。为什么呢?学过网络编程的同学可能知道,视频每一帧数据(例如100x100=10000字节,虽然压缩过,但你不能保证每一帧压缩都少于1500B吧?)往往是大于以太网协议最大组包1500个字节,必须需要拆包组包。

换句话说,VCL是编码后的视频数据,而NAL(网络抽象层)则是对VCL的拆分,以方便传输,即两者是同一数据的不同表达形式。

下面我们来看看H264的分层结构
由于没有太多时间深入研究,只是研究到NALU的主体,片下面的数据结构暂时未作分析。下面我们来看看前两层。
在这里插入图片描述

1)第一层:
H264码流分两种格式:一种是Annexb字节流的格式;另一种是RTP数据包的格式。前者是目前主流形式,码流中由00 00 00 01或者00 00 01作为分割码流中的每一个NALU,前两个类型的NALU上面已经说了,一般为SPS、PPS类型的NALU,第三个NALU有些编码器可能放I帧类型的NALU,有些则不会。即该格式的码流可看成为"起始码--NALU--起始码--NALU--起始码--NALU......"。
而RTP数据包格式的H264压缩码流则是直接封装NALU,不封装起始码,但每一个NALU之前又额外封装了几个字节表示NALU的长度。换句话说,RTP的格式相当于将起始码封装进了NALU中,道理一样。所以该格式看作为"NALU--NALU--NALU",但此方式的NALU有额外的长度信息。
2)第二层:
只讲Annexb字节流的格式。该NALU由一个字节的NALU头和NALU主体组成。
头部1个字节:forbidden_zero_bit(1bit) + nal_ref_idc(2bit) + nal_unit_type(5bit)。
其中:
1、forbidden_zero_bit: 禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
2、nal_ref_idc:
nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。
3、nal_unit_type:
NALU类型取值如下表所示:
在这里插入图片描述

然后拿出NALU比较重要的类型分析。
首先先了解一下:
SEI、SPS、PPS这三种NALU不属于帧的范畴,即它们是视频的相关信息,不会被显示到画面中去,只是属于NALU的某一类型。所以NALU的类型又可以分为VCL NALU(1-5)和非VCL NALU(6-31)。0不使用,所以不计算在内。
5)
IDR(Instantaneous Decoding Refresh):即时解码刷新,即我们的I帧。
6)
SEI(Supplemental enhancement information):附加增强信息,包含了视频画面定时等信息,一般放在主编码图像数据之前,在某些应用中,它可以被省略掉。
7)
SPS(Sequence Parameter Sets):序列参数集,作用于一系列连续的编码图像,即将I、B、P帧连成完整的一帧。
8)
PPS(Picture Parameter Set):图像参数集,作用于编码视频序列中一个或多个独立的图像,即将一帧或多帧连成某个时长的画面。
10)
End:结束位。标志SODB的结束。
12)
Padding:填充位。用于再OBSP基础上添加一个"1bit"和若干个"0bit"用于字节对齐。

2 分析NALU的主体

NALU的主体我们可以认为是RBSP,它是在原始数据SODB的基础上在尾部添加一位1和若干位0的原始字节序列载荷;而又为了防止当NALU主体数据出现00 00 ,然后后面再加01 或者00 01就有可能与起始码相同的情况下,我们又扩展出:每当遇到两个00 00 的时候,就添加一个0x3进去,当解码时又把它忽略掉,这样就能够防止出现数据二义性,这种加了0x3的NALU主体叫做EBSP。所以NALU的主体是有EBSP->RBSP->SODB组成的。这里需要注意一下:我们一般指主体时都指RBSP多一点,但是解码时都要将0x3去掉才能算是完整的RBSP数据类型。
RBSP存储的数据类型可以认为就是上面表的32种类型。由于本人只研究到RBSP,所以H264就先到这里了,有空我会把剩下的层梳理清楚再补充上来。
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值