H264协议

本文深入解析H264编码技术,包括I帧、P帧、B帧的工作原理及其在视频压缩中的作用,阐述了帧间和帧内压缩策略。同时介绍了NAL单元(NALU)结构,包括NALU头信息和类型,以及在不同应用场景下的选择。此外,讨论了GOP、SPS和PPS等概念,对于理解H264编码流程和网络传输的重要性具有指导意义。
摘要由CSDN通过智能技术生成

简介

H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。

H264编码原理

在⾳视频传输过程中,视频⽂件的传输是⼀个极大的问题;⼀段分辨率为1920*1080,每个像素点为RGB占⽤3个字节,帧率是25的视频,对于传输带宽的要求是:
1920*1080*3*25/1024/1024=148.315MB/s,换成bps则意味着视频每秒带宽为1186.523Mbps,这样的速率对于网络络存储是不可接受的,因此视频压缩和编码技术应运而生。

对于视频文件来说,视频由单张图⽚帧所组成,比如每秒25帧,但是图片帧的像素块之间存在相似性,因此视频帧图像可以进⾏图像压缩;H264采⽤了16*16的分块⼤⼩对,视频帧图像进⾏相似⽐较和压缩编码。如下图所示:

在这里插入图片描述

H264中的I帧、P帧和B帧

H264使⽤帧内压缩和帧间压缩的⽅式提⾼编码压缩率;H264采⽤了独特的I帧、P帧和B帧策略
来实现,连续帧之间的压缩。

在这里插入图片描述

压缩率:B帧 > P帧 > I帧

I帧

intra picture:帧内编码帧

I 帧通常是每个 GOP(MPEG 所使⽤的⼀种视频压缩技术)的第⼀个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象,I帧可以看成是⼀个图像经过压缩后的产物。

⾃身可以通过视频解压算法解压成⼀张单独的完整的图⽚

I帧特点:
  • 它是⼀个全帧压缩编码帧,它将全帧图像信息进⾏JPEG压缩编码及传输。
  • 解码时仅⽤I帧的数据就可重构完整图像
  • I帧描述了图像背景和运动主体的详情
  • I帧不需要参考其他画⾯⽽⽣成
  • I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量)
  • I帧是帧组GOP的基础帧(如果为IDR则为第⼀帧),在⼀组中只有⼀个IDR帧,⼀个或多个I
    帧(包括IDR帧)。
  • I帧不需要考虑运动⽮量
  • I帧所占数据的信息量⽐较⼤
P帧

predictive-frame:前向预测编码帧

通过充分将低于图像序列中前⾯已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧。

需要参考其前⾯的⼀个I frame 或者P frame来⽣成⼀张完整的图片

P帧表示的是这⼀帧跟之前的⼀个关键帧(或P帧)的差别,解码时需要用之前缓存的画⾯叠加上本帧定义的差别生成最终画面。(也就是差别帧,P帧没有完整画⾯数据,只有与前⼀帧的画⾯差别的数据)。

P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动⽮量,取预测差值和运动⽮量⼀起传送。在接收端根据运动⽮量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从⽽可得到完整的P帧。

P帧特点:
  • P帧是I帧后⾯相隔1~2帧的编码帧
  • P帧采⽤运动补偿的⽅法传送它与前⾯的I或P帧的差值及运动⽮量(预测误差)
  • 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像
  • P帧属于前向预测的帧间编码,它只参考前⾯最靠近它的I帧或P帧。
  • P帧可以是其后⾯P帧的参考帧,也可以是其前后的B帧的参考帧。
  • 由于P帧是参考帧,它可能造成解码错误的扩散。
  • 由于是差值传送,P帧的压缩比较高。
B帧

bi-directional interpolated prediction frame:双向预测帧

既考虑与源图像序列前⾯已编码帧,也顾及源图像序列后⾯已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧。

需要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚

B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂),换⾔之,要解码B帧,不仅要取得之前的缓存画⾯,还要解码之后的画⾯,通过前后画⾯的与本帧数据的叠加取得最终的画⾯。B帧压缩率⾼,但是解码时CPU会⽐较累。

B帧的预测与重构:B帧以前⾯的I或P帧和后⾯的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动⽮量,并取预测差值和运动⽮量传送。接收端根据运动⽮量在两个参考帧中“找出(算出)”预测值并与
差值求和,得到B帧“某点”样值,从⽽可得到完整的B帧。

B帧特点

  • B帧是由前⾯的I或P帧和后⾯的P帧来进⾏预测的

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

  • B帧是双向预测编码帧

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

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

    注:I、B、P各帧是根据压缩算法的需要,是⼈为定义的,它们都是实实在在的物理帧。⼀般来
    说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可⻅使⽤B帧能节省⼤量
    空间,节省出来的空间可以⽤来保存多⼀些I帧,这样在相同码率下,可以提供更好的画质。

IDR帧

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

I和IDR帧都使⽤帧内预测。I帧不⽤参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。

比如

原始图像:IDR1 B2 B3 P4 B5 B6 P7 B8 B9 I10 B11 B12 P13 B14 B15 P16

解码顺序:IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15

这⾥的B8可以跨过I10去参考P7

原始图像:IDR1 B2 B3 P4 B5 B6 P7 IDR8 B9 B10 P11 B12 P13 B14 B15 P16

解码顺序:IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12 P13 P16 B14 B15

这⾥的B9就只能参照IDR8和P11,不可以参考IDR8前⾯的帧。

IDR核⼼作⽤是,是为了解码的重同步,当解码器解码到 IDR 图像时,⽴即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始⼀个新的序列。这样,如果前⼀个序列出现重⼤错误,在这⾥可以获得重新同步的机会。IDR图像之后的图像永远不会使⽤IDR之前的图像的数据来解码。

⼀个序列就是⼀段内容差别不是很⼤的图像编码后生成的⼀串数据流。当运动变化比较少的时候,⼀个序列可以很长,因为运动变化的少就代表图像画⾯的内容变动很小,所以就可以编⼀个I帧,然后⼀直P帧、B帧了。当运动变化多时,可能⼀个序列就比较短了,比如就包含⼀个I帧和3、4个P帧。

下⾯是⼀个H264码流的举例(从码流的帧分析可以看出来B帧不能被当做参考帧):

在这里插入图片描述

I0 B40 B80 B120 P160

I0 B160

GOP

group of pictures。GOP 指的就是两个I帧之间的间隔。比如说GOP为120,如果是720 p60 的话,那就是2s⼀次I帧.

Reference(参考周期)指两个P帧之间的距离,⼀个I帧所占⽤的字节数⼤于⼀个P帧,⼀个P帧所占⽤的字节数⼤于⼀个B帧。所以在码率不变的前提下,GOP值越⼤,P、B帧的数量会越多,平均每个I、P、B帧所占⽤的字节数就越多,也就更容易获取较好的图像质量;Reference越⼤,B帧的数量越多,同理也
更容易获得较好的图像质量。

需要说明的是,通过提⾼GOP值来提⾼图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会⾃动强制插⼊⼀个I帧,此时实际的GOP值被缩短了。另⼀⽅⾯,在⼀个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响应的时间也越⻓。

编码结构

H264除了实现了对视频的压缩处理之外,为了⽅便⽹络传输,提供了对应的视频编码和分⽚策略;类似于⽹络数据封装成IP帧,在H264中将其称为组(GOP, group of pictures)、⽚(slice)、宏块(Macroblock)这些⼀起组成了H264的码流分层结构;H264将其组织成为序列(GOP)、图⽚(pictrue)、⽚(Slice)、宏块(Macroblock)、⼦块(subblock)五个层次。

GOP(图像组)主要⽤作形容⼀个IDR帧到下⼀个IDR帧之间的间隔了多少个帧。

在这里插入图片描述

H264将视频分为连续的帧进⾏传输,在连续的帧之间使⽤I帧、P帧和B帧。同时对于帧内而⾔,将图像分块为⽚、宏块和字块进⾏分⽚传输;通过这个过程实现对视频⽂件的压缩包装。

NALU

在这里插入图片描述

SPS:序列参数集,SPS中保存了⼀组编码视频序列(Coded video sequence)的全局参数。

PPS:图像参数集,对应的是⼀个序列中某⼀幅图像或者某⼏幅图像的参数。

I帧:帧内编码帧,可独⽴解码⽣成完整的图⽚。

P帧: 前向预测编码帧,需要参考其前⾯的⼀个I 或者B 来⽣成⼀张完整的图⽚。

B帧: 双向预测内插编码帧,则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。

发I帧之前,⾄少要发⼀次SPS和PPS。

NALU结构

H.264原始码流(裸流)是由⼀个接⼀个NALU组成,它的功能分为两层,VCL(视频编码层)和NAL(⽹络提取层)。

VCL:包括核⼼压缩引擎和块,宏块和⽚的语法级别定义,设计⽬标是尽可能地独⽴于⽹络进⾏⾼效的编码。
NAL:负责将VCL产⽣的⽐特字符串适配到各种各样的⽹络和多元环境中,覆盖了所有⽚级以上的语法级别。

在VCL进⾏数据传输或存储之前,这些编码的VCL数据,被映射或封装进NAL单元。

⼀个NALU = ⼀组对应于视频编码的NALU头部信息 + ⼀个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)

NALU结构单元的主体结构如下所示;⼀个原始的H.264 NALU单元通常由[StartCode] [NALU Header] [NALU Payload]三部分组成,其中 Start Code ⽤于标示这是⼀个NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP。

在这里插入图片描述

对于FFmpeg解复⽤后,MP4⽂件读取出来的packet是不带startcode,但TS⽂件读取出来的packet带了startcode。

NALU Header

在这里插入图片描述

F:(forbidden_zero_bit)禁止位,1位,当网络发现NAL单元有比特错误时,可设置该比特为1,以便接收方丢掉该单元。在 H.264 规范中规定了这⼀位必须为 0。

NRI:(nal_ref_ide)重要性指示位,标志该NAL单元用于重建时的重要性,值越大,越重要,取值00~11。00的NALU解码器可以丢弃它而不影响图像的回放,不过一般情况下不太关心这个属性。如果当前NAL是属于参考帧的⽚,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需⼤于0。

TYPE:(nal_unit_type)NALU类型,123表示单个NAL包,2431需要分包或者组合发送。第一个字节的第五位。


0:没有定义

1~23是NAL单元,单个NAL单元包。

1:不分区,非IDR图像的片。 非IDR图像的编码条带 slice P帧

2:片分区A 编码条带数据分割块A slice DPA

3:片分区B 编码条带数据分割块B slice DPB

4:片分区C 编码条带数据分割块C slice DBC

5:IDR图像中的片 IDR图像的编码条带 slice IDR 关键帧 I帧

6:补充增强信息单元(SEI)

7:SPS(Sequence Parameter Set)序列参数集,作用于一串连续的视频图像,即视频序列。

8:PPS(Picture Parameter Set)图像参数集,作用于视频序列中的一个或多个图像。

9:序列结束

10:序列结束

11:码流结束

12:填充

13~23:保留

24:STAP-A单一时间的组合包

25:STAP-B单一时间的组合包

26:MTAP16单一时间的组合包

27:MTAP24多个时间的组合包

28:FU-A分片的单元

29:FU-B分片的单元

30、31:未定义


start code

H.264标准指出,当数据流是储存在介质上时,在每个NALU 前添加起始码:0x000001 或0x00000001,用来指示⼀个NALU 的起始和终⽌位置:

在这样的机制下,在码流中检测起始码,作为⼀个NALU得起始标识,当检测到下⼀个起始码时,当前NALU结束。

3字节的 0x00 00 01 只有⼀种场合下使用,就是⼀个完整的帧被编为多个slice(片)的时候,包含这些slice的NALU 使用3字节起始码,其余场合都是4字节 0x00 00 00 01的。

H264 annexb模式

H264有两种封装

  • ⼀种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中。
  • ⼀种是mp4模式,⼀般mp4 mkv都是mp4模式,没有startcode,SPS和PPS以及其它信息被封装在container中,每⼀个frame前⾯4个字节是这个frame的⻓度。

很多解码器只⽀持annexb这种模式,因此需要将mp4做转换, 在ffmpeg中用h264_mp4toannexb_filter可以做转换。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值