H264帧格式解析

文章目录

H264帧基础知识

一组图像 GOP

IDR帧与I帧

P帧

B帧

H264 profile level

H264码率控制

H264 Annexb byte-stream格式

NALU header

NALU start-code

H264 AVCC格式

extradata结构详解

H264 Annexb与AVCC格式转换

H264 Annexb转为AVCC

AVCC 转为 H264 Annexb

进入音视频领域也快一年了,空闲时间思考一下,觉得有必要把一些关于H264与流媒体的知识总结一下,对自己在音视频领域内的知识进行梳理,不至于随着时间的流逝而遗忘。

H264帧基础知识

一组图像 GOP

所谓GOP就是1组图像Group of Picture,在这一组图像中有且只有1个I帧,多个P帧或B帧,两个I帧之间的帧数,就是一个GOP。

GOP一般设置为编码器每秒输出的帧数,即每秒帧率,一般为25或30,当然也可设置为其他值。

在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP 开始才有可能得以恢复,所以GOP值也不宜设置过大。

由于P、B帧的复杂度大于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过长的GOP还会影响Seek操作的响应速度,由于P、B帧是由前面的I或P帧预测得到的,所以Seek操作需要直接定位,解码某一个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越长,需要解码的预测帧就越多,seek响应的时间也越长。

IDR帧与I帧

在I帧中,所有宏块都采用帧内预测的方式,因此解码时仅用I帧的数据就可重构完整图像,不需要参考其他画面而生成。

H.264中规定了两种类型的I帧:普通I帧(normal Iframes)和IDR帧(InstantaneousDecoding Refresh, 即时解码刷新)。 IDR帧实质也是I帧,使用帧内预测。IDR帧的作用是立即刷新,会导致DPB(Decoded Picture Buffer参考帧列表)清空,而I帧不会。所以IDR帧承担了随机访问功能,一个新的IDR帧开始,可以重新算一个新的Gop开始编码,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。如果一个视频中没有IDR帧,这个视频是不能随机访问的。所有位于IDR帧后的B帧和P帧都不能参考IDR帧以前的帧,而普通I帧后的B帧和P帧仍然可以参考I帧之前的其他帧。IDR帧阻断了误差的积累,而I帧并没有阻断误差的积累。

一个GOP序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像,但I帧不一定都是IDR帧,只有GOP序列的第1个I帧是IDR帧。

I帧:帧内编码帧 ,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)

它是一个帧内压缩编码帧,压缩比约为7。它将全帧图像信息进行JPEG压缩编码及传输;

解码时仅用I帧的数据就可重构完整图像;

I帧描述了图像背景和运动主体的详情;

I帧不需要参考其他画面而生成;

I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;

I帧不需要考虑运动矢量;

I帧所占数据的信息量比较大。

疑问:按照GOP、IDR帧、I帧的解释,如果一个GOP出现除去第一个IDR帧之外的I帧,是不存在的,那这样的话,就不存在非IDR的I帧了,可是为什么还要说明非IDR的I帧呢。

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

P帧

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帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,约为50,但是解码时CPU会比较累。

B帧是由前面的I或P帧和后面的P帧来进行预测的

B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量

B帧是双向预测编码帧

B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;

B帧不是参考帧,不会造成解码错误的扩散。

H264 profile level

BP-Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;

EP-Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;

MP-Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),也支持CAVLC 和CABAC 的支持;

HP-High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、无损视频编码和更多的YUV 格式。

一般可以输出H264帧的USB摄像头,使用的是BP-Baseline Profile,只有I帧与P帧。

H264码率控制

VBR:Variable BitRate,动态比特率,其码率可以随着图像的复杂程度的不同而变化,因此其编码效率比较高,Motion发生时,马赛克很少。码率控制算法根据图像内容确定使用的比特率,图像内容比较简单则分配较少的码率(似乎码字更合适),图像内容复杂则分配较多的码字,这样既保证了质量,又兼顾带宽限制。这种算法优先考虑图像质量。

ABR:Average BitRate,平均比特率 是VBR的一种插值参数。ABR在指定的文件大小内,以每50帧 (30帧约1秒)为一段,低频和不敏感频率使用相对低的流量,高频和大动态表现时使用高流量,可以做为VBR和CBR的一种折衷选择。

CBR:Constant BitRate,是以恒定比特率方式进行编码,有Motion发生时,由于码率恒定,只能通过增大QP来减少码字大小,图像质量变差,当场景静止时,图像质量又变好,因此图像质量不稳定。优点是压缩速度快,缺点是每秒流量都相同容易导致空间浪费。

CVBR:Constrained Variable it Rate,VBR的一种改进,兼顾了CBR和VBR的优点:在图像内容静止时,节省带宽,有Motion发生时,利用前期节省的带宽来尽可能的提高图像质量,达到同时兼顾带宽和图像质量的目的。这种方法通常会让用户输入最大码率和最小码率,静止时,码率稳定在最小码率,运动时,码率大于最小码率,但是又不超过最大码率。

H264 Annexb byte-stream格式

SODB:String of Data Bits,数据 bit 流,最原始的编码数据

RBSP:Raw Byte Sequence Payload,原始字节序列载荷,在SODB的后面填加了结尾比特,RBSP trailing bits 一个bit“1”,若干比特“0”,以便字节对齐

EBSP:Encapsulated Byte Sequence Payload,扩展字节序列载荷,在RBSP基础上填加了仿校验字节(0x03)。

Start-code:在NALU加到Annexb即byte-stream格式时,需要在每组NALU之前添加开始码StartCode,如果该NALU对应的slice为1个GOP开始则用4位字节表示,0x00000001,否则用3位字节表示0x000001(也不一定)。

NALU header

bit位描述

F

禁止位,0表示正常,1表示错误,一般都是0

NRI

重要级别,11表示非常重要,一般取值为11、10、01

Type:nal_unit_type

表示该NALU的类型是什么,类型的具体取值可见下表

nal_unit_typeNAL类型

0

未使用

1

非IDR的片

2

片数据A分区

3

片数据B分区

4

片数据C分区

5

一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧

6

补充增强信息单元(SEI)

7

序列参数集(SPS)

8

图像参数集(PPS)

9

分界符

10

序列结束

11

码流结束

12

填充

13…23

保留

24…31

未使用

NALU Header常见的取值:0x67 0x68 0x65 0x61,0x47 0x48 0x45 0x41,0x27 0x28 0x25 0x21

NALU header描述

0x67,0x47,0x27

SPS, 序列参数集,重要级别分别为11、10、01

0x68,0x48,0x28

PPS,图像参数集,重要级别分别为11、10、01

0x65,0x45,0x25

IDR帧,重要级别分别为11、10、01

0x61,0x41,0x21

非IDR帧,重要级别分别为11、10、01

NALU start-code

一个NALU包中的数据并不包含它的大小(长度)信息,因此不能简单的连接NALU包来建立一个流,因为你不知道一个包从哪里结束,另一个包从哪里开始。

Annex B格式用起始码来解决这个问题,即给每个NALU加上前缀码:2个或者3个0x00,后面再加一个0x01, 如:0x000001或者0x00000001。

4字节类型的开始码通常只用于标识流中的随机访问点,如SPS PPS AUD和IDR,然后其他地方都用3字节类型的开始码以减少数据量。

如果该NALU对应的slice为1个GOP开始则用4位字节表示,0x00000001,否则用3位字节表示0x000001(不一定)

防竞争字节:为了使NALU主体中不包括与开始码相冲突的,在编码时,就插入一个字节的0x03;解码时将0x03去掉。也称为脱壳操作。

编码器将每个NAL各自独立、完整地放入一个分组,因为分组都有头部,解码器可以方便地检测出NAL的分界,并依次取出NAL进行解码。每个NAL前有一个起始码 0x00 00 01(或者0x00 00 00 01),解码器检测每个起始码,作为一个NAL的起始标识,当检测到下一个起始码时,当前NAL结束。同时H.264规定,当检测到0x000000时,也可以表征当前NAL的结束。那么NAL中数据出现0x000001或0x000000时怎么办?H.264引入了防止竞争机制,如果编码器检测到NAL数据存在0x000001或0x000000时,编码器会在最后个字节前插入一个新的字节0x03,这样:

0x000000->0x00000300

0x000001->0x00000301

0x000002->0x00000302

0x000003->0x00000303

解码器检测到0x000003时,把03抛弃,恢复原始数据。解码器在解码时,首先逐个字节读取NAL的数据,统计NAL的长度,然后再开始解码。

H264 AVCC格式

Annex-B:没有NALU长度字节,使用start code分隔NALU,start code为三字节或四字节,0x000001或0x00000001,一般是四字节;SPS和PPS按流的方式写在一组GOP之前。

AVCC:使用NALU长度,固定字节,通常为4字节,分隔NALU;一般在每个NALU头部为4字节大端格式的长度字节,在一组GOP的头部包含extradata结构,用于存储sequence-header、SPS、PPS数据。

虽然AVCC格式不使用起始码,防竞争字节仍然存在

extradata结构详解

namelength, unit: bitvalue

version

8bit

0x01

avc profile

8bit

0x64

avc compatibility

8bit

0x00

avc level

8bit

0x0A

NALULengthSizeMinusOne

8bit

0xFF,高6位保留,默认为1,低2位为11,表示NALU长度用3+1=4字节表示

number of SPS NALUs

8bit

0xE1,高3位保留,低5位表示有几个SPS,通常只有1个SPS

SPS size

16bit

大端格式的SPS长度,0x0019,表示25字节SPS

SPS NALU data

SPS size × 8bit

0x67到0x80,表示SPS数据

number of PPS NALUs

8bit

0x01PPS个数,通常只有1个PPS

PPS size

8bit

0x07,表示PPS的数据长度

PPS NALU data

PPS size × 8bit

0x68到0x30,表示PPS数据

NALULengthSizeMinusOne解释:这个变量告诉我们用几个字节来存储NALU的长度,如果NALULengthSizeMinusOne是0,那么每个NALU使用一个字节的前缀来指定长度,那么每个NALU包的最大长度是255字节,这个明显太小了,使用2个字节的前缀来指定长度,那么每个NALU包的最大长度是64K字节,也不一定够,一般分辨率达到1280*720 的图像编码出的I帧,可能大于64K;3字节是比较完美的,但是因为一些原因(例如对齐)没有被广泛支持;因此4字节长度的前缀是目前使用最多的方式,

H264 Annexb与AVCC格式转换

H264 Annexb转为AVCC

1、对于一个GOP的开始,根据start-code,分离出SPS、PPS帧,并分别计算出长度

2、根据SPS, PPS创建出extradata,附加到GOP的头部

3、从IDR帧开始,搜索start-code,分离出每一个NALU,计算长度,然后将start-code转为4字节的NALU长度

AVCC 转为 H264 Annexb

1、对于一个GOP的开始,首先检索出extradata部分的数据

2、根据extradata数据创建出SPS帧,并用4字节的start-code:0x00000001附加在SPS数据的头部

3、根据extradata数据创建出PPS帧,并用4字节的start-code:0x00000001附加在PPS数据的头部,并将PPS数据连接到SPS后面

4、根据NALU的长度字段,分离出每一个NALU,然后用用4字节的start-code:0x00000001替换长度字段

5、在以上过程中需要计算每一个NALU的长度,尤其是GOP的IDR帧,一般在IDR帧前还有SPS与PPS帧,其长度需要一起计算。

本文对多篇博客进行了参考,进行了总结,着重确定了我想理解的部分,谢谢广大博友的贡献。

(0)

相关推荐

  • 视频编解码基础概念

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10285829.html 本文涉及视频编解码最基础概念,从工程应用角度出发,帮助理解和编写 ...

  • (推荐阅读)H264, H265硬件编解码基础及码流分析

    需求 在移动端做音视频开发不同于基本的UI业务逻辑工作,音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps,pps,v ...

  • 《中医舌诊》,26张临床高清舌诊图,附带解析,史上最全!

    掌纹医学,看手知健康,疾病早知道..... 舌质 色:淡紫.淡白: 形:偏嫩.少量瘀点.轻度齿痕. 舌苔 苔质:薄.润: 苔色:白. [临床意义] 阳虚.气虚.气滞等原因导致的气血瘀滞. 舌质 色:淡 ...

  • 初中数学:二次根式的考点解析 常见误区 隐含条件 经典例题

    成才路上 初中精品学习资料 104篇原创内容 公众号 二次根式是初中数学的一个重要内容,要求了解二次根式和最简二次根式的概念,理解二次根式的性质,熟练地进行二次根式的加减乘除及混合运算. 今天方法君就 ...

  • 高考物理11类重点题型全解析! 附经典例题&详解

    高考理科综合卷中,物理部分选择题有单项和双项选择题两种题型.从最近几年的试题看: 4道单项选择难度低,考查的考点相对稳定且相对单一,涉及的知识点主要有共点力平衡.热力学第一定律.气体状态方程.分子动理 ...

  • 中医解析:指甲半月痕暗藏健康秘密

    医学指导:广东省中医院大德路总院传统疗法中心主任陈秀华教授 "哎呀!我的指甲没有月牙痕,是不是最近我的身体不太好?" 不少朋友开始关注自己指甲上的月牙痕,还有不少人照着网上的一些描 ...

  • 解析52年西南局与西南军政委员会领导人的构成与职级统计(之四)

    (接前文) 第一部分,西南局书记.副书记的评级统计: 刘伯承(52年大军区司令员政委级,55年军委主席副主席级):西南局第二书记(49.10-54.12) 早期革命资历:1926年5月入党,1927年 ...

  • 初中数学重难点解析—几何代数最值问题!

    i初中数学 公众号 几何最值问题是指在一定的条件下,求平面几何图形中某个确定的量(如线段长度.角度大小.图形面积等)的最大值或最小值.在中考中常以填空选择及解答题形式出现,难易程度多为难题.压轴题.务 ...

  • 国家级名老中医毛德西教授:王清任逐瘀汤类方解析

    王清任(1768~1831年)是一位革新派的医学家,他的<医林改错>虽然只有3万余字,但在中医学发展历程中有着举足轻重的作用.特别是他所拟定的逐瘀汤类方,极大地丰富了中医血瘀理论与活血化瘀 ...

  • 关于“炁”的解析与借鉴

    古为今用,洋为中用,取长补短,中西合璧,依然可作为科学探索的一个原则. 1 炁的字理,国学厉害 炁 =旡[ji]/既(原已) 灬(火) =屰[ji]/逆(还原) 燃烧分解 =因燃烧而还原为无形的气 = ...

  • 木枫专业 | 建筑器材租赁业务常见法律风险解析

    在建筑器材租赁业务的实践中, 往往会出现这样或者那样的行业习惯, 在行业中看起来是稀松平常大家都在做的事情, 但是却成了维权之路上的一个又一个雷区. 笔者简要总结了几点, 都是笔者在办案过程中遇到过的 ...