H264 专题

H264 码流结构

首先抛一个经典的264码流结构

概念

H264 专题_第1张图片

H264码流由 Nal Unit 组成,每个Nalu承载着视频信息,视频的每一帧都被分割成一个或多个块,存放到Nalu当中。

GOP:视频序列,由一个I帧、多个P帧、B帧以及SPS、PPS、SEI构成

RBSP:Nalu body 

Start Code: {0x00, 0x00, 0x00, 0x03} 或 {0x00, 0x00, 0x03},在一些h264码流中一帧的开始的StartCode 是0003;

Nalu Header:

Name bit Desciription
Forbiden_Bit 1 禁止位,0表示正常,1表示错误,一般都是0
NRI 2 重要级别,11表示非常重要,一般取值为11、10、01
Nalu_Type 5 Nalu 的类型

Nalu Type:

Index Nalu Type
0 未使用
1 非IDR
2 片数据A分区
3 片数据B分区
4 片数据C分区
5 IDR
6 SEI:补充增强信息单元
7 SPS:序列参数集
8 PPS:图像参数集
9 AUD:帧分界符
10 序列结束
11 码流结束
12 填充
13-23 保留
24-31 未使用


片数据A分区、片数据B分区、片数据C分区 概念???

IDR帧: 在编码解码中为了方便,将GOP中首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但I帧不一定是IDR帧;IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。I帧有被跨帧参考的可能,IDR不会。

I帧:帧内编码帧,表示关键帧,可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
它是一个帧内压缩编码帧,压缩比约为7。它将全帧图像信息进行JPEG压缩编码及传输;解码时仅用I帧的数据就可重构完整图像;I帧描述了图像背景和运动主体的详情;I帧不需要参考其他画面而生成;I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;I帧不需要考虑运动矢量;I帧所占数据的信息量比较大。
I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样,例如:
IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15   这里的B8可以跨过I10去参考P7
IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12             这里的B9就只能参照IDR8和P11,不可以参考IDR8前面的帧
H.264引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

H264编码存在多种编码方式CBR、VBR、CVBR、ABR等等,VBR编码模式下图像内容变化差异很大时,会动态调整I帧的数量,因此GOP的概念需要修正:两个IDR帧之间的间隔为一组GOP,一组GOP中可以出现非IDR的I帧。

P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面,P帧没有完整画面数据,只有与前一帧的画面差异的数据。P帧的压缩率20,P帧是I帧后面相隔1~2帧的编码帧;P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;由于P帧是参考帧,它可能造成解码错误的扩散;由于是差值传送,P帧的压缩比较高。
 

B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,约为50,但是解码时CPU会比较累。B帧是由前面的I或P帧和后面的P帧来进行预测的;B帧表示的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;压缩比最高,因为它只反映参考帧间运动主体的变化情况,预测比较准确;B帧不是参考帧,不会造成解码错误的扩散。
 

句法元素中各个参数所占比特数说明:

u(n) 表示n 个比特

ue(v) 表示读取一个无符号哥伦布编码数值 具体占据几个比特要根据读取实际值来计算

se(v)表示读取一个有符号哥伦布编码数值 具体占据几个比特要根据读取实际值来计算

详细解释见H264 规范第9 章节

SPS:Sequence Paramater Set,序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。

H264 专题_第2张图片

H264 专题_第3张图片

H264 专题_第4张图片

H264 专题_第5张图片

H264 专题_第6张图片

PPS:

H264 专题_第7张图片

Slice:

实际保存原始视频的图像数据的部分保存在其他的VCL层的NAL Units中。这部分数据在码流中称作是条带(Slice)。一个Slice包含一帧图像的部分或全部数据,换言之,一帧视频图像可以编码为一个或若干个Slice。一个Slice最少包含一个宏块,最多包含整帧图像的数据。在不同的编码实现中,同一帧图像中所构成的Slice数目不一定相同。 在H.264中设计Slice的目的主要在于防止误码的扩散。因为不同的slice之间,其解码操作是独立的。某一个slice的解码过程所参考的数据(例如预测编码)不能越过slice的边界。

Slice Type:

  • I slice: 帧内编码的条带;
  • P slice: 单向帧间编码的条带;
  • B slice: 双向帧间编码的条带;
  • SI slice: 切换I条带,用于扩展档次中码流切换使用;
  • SP slice: 切换P条带,用于扩展档次中码流切换使用;

在I slice中只包含I宏块,不能包含P或B宏块;在P和B slice中,除了相应的P和B类型宏块之外,还可以包含I类型宏块。

Slice Header:

主要保存了当前slice的一些全局的信息,slice body中的宏块在进行解码时需依赖这些信息。其中比较常见的一些语法元素有:

  1. first_mb_in_slice: 当前slice中包含的第一个宏块在整帧中的位置;
  2. slice_type:当前slice的类型;
  3. pic_parameter_set_id:当前slice所依赖的pps的id;
  4. colour_plane_id:当标识位separate_colour_plane_flag为true时,colour_plane_id表示当前的颜色分量,0、1、2分别表示Y、U、V分量。
  5. frame_num:表示当前帧序号的一种计量方式。
  6. field_pic_flag:场编码标识位。当该标识位为1时表示当前slice按照场进行编码;该标识位为0时表示当前slice按照帧进行编码。
  7. bottom_field_flag:底场标识位。该标志位为1表示当前slice是某一帧的底场;为0表示当前slice为某一帧的顶场。
  8. idr_pic_id:表示IDR帧的序号。某一个IDR帧所属的所有slice,其idr_pic_id应保持一致。该值的取值范围为[0,65535]。
  9. pic_order_cnt_lsb:表示当前帧序号的另一种计量方式。
  10. delta_pic_order_cnt_bottom:表示顶场与底场POC差值的计算方法,不存在则默认为0;
  11. slice_qp_delta:用于计算当前slice内所使用的初始qp值

H264 专题_第8张图片

 

 

 

 

你可能感兴趣的:(音视频学习)