H.264及结构组成

H.264: H.264/AVC项目的目的是为了创建一个比以前的视频压缩标准,
//AVC指不包含svc的H264视频,一般意义上的h264,scv是后面加进去的,一半叫vc
在更低的比特率的情况下依然能够提供良好视频质量的标准
(如,一半或者更少于MPEG-2,H.263,或者MPEG-4 Part2 )。
优势:
1)网络亲和性,即可适用于各种传输网络
2)高的视频压缩比,当初提出的指标是比 H.263,MPEG-4,约为它们的2

原理简介:
  H.264 原始码流(又称为裸流),是有一个接一个的 NALU 组成的,而它的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer)。
  VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据 序列。在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中。每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特。一个 bit“1”若干比特“0”,以便字节对齐。
  在这里插入图片描述
 上图中的 NALU头 + RBSP 就相当与一个 NALU (Nal Unit), 每个单元都按独立的 NALU 传送。 其实说白了,H.264 中的结构全部都是以 NALU 为主的,理解了 NALU,就理解 H.264 的结构了。
在这里插入图片描述

(切)片slice

一帧(=一张图片)→编码→一个or多个片slice --------NALU是片的载体

片的主要作用是用作宏块(Macroblock)的载体,片之所以被创造出来,主要目的是为限制误码的扩散和传输。
如何限制误码的扩散和传输?
每个片(slice)都应该是互相独立被传输的,某片的预测(片(slice)内预测和片(slice)间预测)不能以其它片中的宏块(Macroblock)为参考图像。

我们可以理解为一 张/帧 图片可以包含一个或多个分片(Slice),而每一个分片(Slice)包含整数个宏块(Macroblock),即每片(slice)至少一个 宏块(Macroblock),最多时每片包 整个图像的宏块。

上图结构中,我们不难看出,每个分片也包含着头和数据两部分:
分片slice=分片头(Slice Header) + 若干宏块
1、分片头中包含着分片类型、分片中的宏块类型、分片帧的数量、分片属于那个图像以及对应的帧的设置和参数等信息。
2、分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
片(slice)通过 NALU 装载并进行网络传输的
NALU 内可以是切片,也可能装载着其他用作描述视频的信息

片slice是H264提出的新概念,,是通过编码图片后切分通过高效的方式整合出来的概念,一张图片至少有一个或多个片(slice)。

宏块

宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。
组成部分:一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成。每个图象中,若干宏块被排列成片的形式。
在这里插入图片描述

切片(slice)类型跟宏块类型的关系

对于切片(slice)来讲,分为以下几种类型:

0 P-slice. Consists of P-macroblocks (each macro block is predicted using one reference frame) and / or I-macroblocks.
1 B-slice. Consists of B-macroblocks (each macroblock is predicted using one or two reference frames) and / or I-macroblocks.
2 I-slice. Contains only I-macroblocks. Each macroblock is predicted from previously coded blocks of the same slice.
3 SP-slice. Consists of P and / or I-macroblocks and lets you switch between encoded streams.
4 SI-slice. It consists of a special type of SI-macroblocks and lets you switch between encoded streams.

I片:只包 I宏块,I 宏块利用从当前片中已解码的像素作为参考进行帧内预测(不能取其它片中的已解码像素作为参考进行帧内预测)。

P片:可包 P和I宏块,P 宏块利用前面已编码图象作为参考图象进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即 16×16、16×8、8×16 或 8×8 亮度像素块(以及附带的彩色像素);如果选了 8×8 的子宏块,则可再分成各种子宏块的分割,其尺寸为 8×8、8×4、4×8 或 4×4 亮度像素块(以及附带的彩色像素)。

B片:可包 B和I宏块,B 宏块则利用双向的参考图象(当前和 来的已编码图象帧)进行帧内预测。

SP片(切换P):用于不同编码流之间的切换,包含 P 和/或 I 宏块

SI片:扩展档次中必须具有的切换,它包 了一种特殊类型的编码宏块,叫做 SI 宏块,SI 也是扩展档次中的必备功能。

整体结构

在这里插入图片描述
在这里插入图片描述
GOP (图像组)主要用作形容一个 i 帧 到下一个 i 帧之间的间隔了多少个帧,增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了。

1.3. 编码分类
软件编码(简称软编):使用CPU进行编码。
硬件编码(简称硬编):不使用CPU进行编码,使用显卡GPU,专用的DSP、FPGA、ASIC芯片等硬件进行编码。
优缺点

①软编:实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较硬编码低,低码率下质量通常比硬编码要好一点。
②硬编:【性能高】,低码率下通常质量低于硬编码器,但部分产品在GPU硬件平台移植了优秀的软编码算法(如X264)的,质量基本等同于软编码。

DTS和PTS

DTS:主要用于视频的解码,在解码阶段使用.
PTS:主要用于视频的同步和输出.在渲染的时候使用.在没有B frame的情况下.DTS和PTS的输出顺序是一样的。
在这里插入图片描述
I帧的解码不依赖于任何的其它的帧.而P帧的解码则依赖于其前面的I帧或者P帧.B帧的解码则依赖于其前、后的最近的一个I帧或者P帧

H264基本原理

H264基本原理

GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。如下图所示:
在这里插入图片描述

H.264的功能分两层:
VCL (VideoCoding Layer,视频编码层):负责高效的视频内容表示。
NAL(NetworkAbstraction Layer,网络抽象层):负责以网络所要求的恰当的方式对数据进行打包和传送NALU。

VCL只关心编码部分,重点在于【编码算法以及在特定硬件平台的实现】
VCL输出的是编码后的纯视频流信息XX.h264,没有任何冗余头信息
NAL关心的是VCL的输出纯视频流【如何被表达和封包以利于网络传输】
总结:做编码器的人关心的是VCL部分;做视频传输和解码播放的人关心的是NAL部分

I、P、B、IDR帧

视频数据主要有两类数据冗余:
  ①空间冗余:→帧内压缩 I帧压缩
  ②时间冗余:→帧间压缩: P帧与B帧的压缩算法

下图以h264的码流结构为例,如果是h265则在sps前还有vps.
在这里插入图片描述

补充: I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50. 但是iOS中一般不开启B帧,因为B帧的存在会导致时间戳同步较为复杂.

①i帧 i frame, intra picture 非参考帧/独立帧
通常是GOP的第一个帧(即IDR),也可能在一个序列中间插入I帧
来源:帧内压缩(去除帧内空间冗余信息)称为帧内编码帧

一般而言,每秒视频至少需要1个I帧,每秒里增加I帧可以改善质量,但增加网络带宽和网络负载
I帧丢失→随后的P帧也就无法解析

②P帧,前向搜索帧/前向预测帧,以I帧预测P帧
  只参考前面多个I帧和P帧

③B帧,双向搜索帧/双向参考帧,由I帧、P帧预测B帧
  【参考前面&后面的最近的I帧和P帧】

④IDR = instantaneous decoding refresh 即时解码刷新
  一个序列的第一个图像帧叫做 IDR 图像(立即刷新图像,属于特殊的I帧)。
  目的:【为了解码的重同步】
    当解码器解码到 IDR 图像时【相当于向解码器发送了一个清理reference buffer的信号】,立即将参考帧队列清空【驱动器参数块DPB(decord picture buff 参考帧列表)→导致PPS、SPS参数更新】,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。【如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。】
  还有:“因为264采用了多帧预测,就有可能在display order下I帧后的P会参考I帧前的帧,这样在random access时如果只找I帧,随后的帧的参考帧可能unavailable,IDR就是这样一种特殊的I帧,把它定义为确保后面的P一定不参考其前面的帧,可以放心地random access。 ”
  为了取得更高的图像质量,在一个视频文件中有好多个IDR帧

在这里插入图片描述

这里要提一下,当编码器处理完IDR帧遇到B帧时,编码期先把其放入缓存器中存放起来。直接对P进行编码。即编码器中编码的实际顺序是IDR P B B P B B……即1423756……

H.264中:数据流层次结构:
码流、序列、帧、片组、片(I、P、B、SP、SI片)、NALU、宏块MB macroblock、亚宏块、块、像素

①序列GOP,就是一段连续图像帧且画面之间变化不大。
  图像就是一个序列。当某个帧与前面的帧图像变化很大,无法参考前面帧生成时,就要开始一个新序列。
  ②帧:有1个或多个片组,如果不采用FMO(灵活宏块排序)机制,则一帧只有一个片组
  ③片组:包含1个片(slice)或多个片
  ④片:slice,由宏块组成,如果不采用DP(数据分割)机制,1个片只包含1个NALU,否则1个片由3个NALU组成,nal_unit_type值等于2、3、4的NALU属于同一个片
分片的目的是限制误码的扩撒和传输,使片间保持独立,[ [slice header] [slice data] ]
[slice header] 说明了片类型、属于哪个帧、参考帧等
[slice data] 里是整数个宏块
  ⑤宏块:编码处理的基本单元,由多个块组成,通常宏块大小为16X16像素,分为I、B、P宏块
  ⑥块:一个编码图像要划分成多个块才能进行处理,一个块是4X4像素

图像解码过程是按照slice进行解码,然后按照片组将解码宏块重组成图像

H264的序列GOD和NALU

6.4.H264的NAL单元详解2
在这里插入图片描述
NALU 单元= [StartCode] [NALU Header] [NALU Payload] 三部分循环组成
在这里插入图片描述

sei 6=00110 补充增强信息(SEI)
  没有图像数据信息,只是对图像数据信息或者视频流的补充,有些内容可能对解码有帮助。
sps 7=00111 序列参数集(SPS)  一般搭配重要性11→0x67
  【图像格式信息,编码参数信息,与参考图像相关的信息,档次、层和级相关信息等】
pps 8=01000 图像参数集(PPS) 一般搭配重要性11→0x68
  GOD图像所用的【公共参数】

这三者一般位于序列最前面
但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:
  解码器需要在码流中间开始解码;
  编码器在编码的过程中改变了码流的参数(如图像分辨率等);
在做视频播放器时,为了让后续的解码过程可以使用SPS中包含的参数,必须对其中的数据进行解析。
H264码流中SPSPPS详解

SPS中的:档次(Profile)、层(Tier)和级别(Level)

①Profile:档次: 主要规定编码器可采用哪些【编码工具或算法】。
  对视频压缩特性的描述(CABAC呀、颜色采样数等等)Baseline/Main/High Profile。
----------- profile_idc:
标识当前H.264码流的profile。
H.264中定义了三种常用的档次profile:-----对应编码工具的集合
基准档次:baseline profile; 66
主要档次:main profile; 77
扩展档次:extended profile; 88
   Profile越高,就说明采用了越高级的压缩特性。
在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。
另外,constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。

②Level:
  根据解码端的负载和存储空间情况对关键参数【最大采样率、最大图像尺寸、分辨率、最小压缩比、最大比特率、解码缓冲区DPB大小等】加以限制。
//https://blog.csdn.net/xiaojun111111/article/details/52090185
   Level越高,视频的码率、分辨率、fps越高。
--------------------------level_idc
标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。
当前码流中,level_idc = 0x1e = 30,因此码流的级别为3。

sequence序列GOD

(1)一段h.264的码流其实就是多个sequence组成的
(2)sample中每个sequence均有固定结构:1sps+1pps+1sei+1I帧+若干p帧
(3)sps和pps和sei描述该sequence的图像信息,这些信息有利于网络传输或解码
(4)I帧是关键,丢了I帧整个sequence就废了,每个sequence有且只有1个I帧
(5)p帧的个数等于fps-1
(6)I帧越大则P帧可以越小,反之I帧越小则P帧会越大
(7)I帧的大小取决于图像本身内容,和压缩算法的空间压缩部分
(8)P帧的大小取决于图像变化的剧烈程度
(9)CBR和VBR下P帧的大小策略会不同,
CBR(Constants BitRate即静态码率 尽量保障码率率)时P帧大小基本恒定,
VBR(Variable Bitrate动态码率 尽量保障清晰度波动小)时变化会比较剧烈

时间戳rtp_timestamp:

https://blog.csdn.net/jasonhwang/article/details/7316128
RTP timestamp是用时钟频率(clock rate)计算而来表示时间的。
RTP timestamp表示每帧的时间标签
特征:【不同帧的时间戳不同,同一帧的时间戳相同】

识别2包数据是否来自于同一个NALU拆分所得:
  ①通过每帧最后一个RTP的marker标志区别帧
  ②最可靠的方法是查看相同RTP timestamp包为同一帧。

计算:两帧之间RTP timestamp的增量 = 时钟频率 / 帧率
其中时钟频率可从SDP中获取,如:https://www.cnblogs.com/idignew/p/7249056.html
m=video 2834 RTP/AVP 96
a=rtpmap:96 H264/90000
通常视频时钟频率为90000、通常音频的时钟频率一般为8000。
若视频帧率为25fps,则相邻帧间RTP timestamp增量值 = 90000/25 = 3600。

量化参数QP:

【QP值对应量化步长】,对于亮度而言,此值范围为int=0~51 。值越小,量化步长越小,量化的精度就越高,意味着同样画质的情况下,产生的数据量可能会更大。
QP值每增加6,量化步长就增加一倍。

现有的码率控制算法主要是通过【调整离散余弦变换的量化参数大小输出目标码率】。实际上,量化参数(QP)反映了空间细节压缩情况,如QP小,大部分的细节都会被保留;QP增大,一些细节丢失,码率降低,但图像失真加强和质量下降。也就是说,QP和比特率(每秒传输的比特数bit)成反比的关系,而且随着视频源复杂度的提高,这种反比关系会更明显

发布了81 篇原创文章 · 获赞 1 · 访问量 2896

猜你喜欢

转载自blog.csdn.net/qq_42024067/article/details/100039579