流媒体-H264编码基础

H264编码基础

前言

视频原始数据通常很大,例如,分辨率是1280*720,帧率是25的视频,那么一秒所产生正常的数据大小为:

1280*720(位像素)*25(张) / 8(1字节8位)(结果:B) / 1024(结果:KB) / 1024 (结果:MB) = 2.75MB

这样的视频在网络上进行传输数据量无疑非常大,对网络带宽的要求也非常高,视频编解码的作用就在于将视频数据进行编码压缩,保证视频一定质量的前提下,减少传输的数据量。
H264编码属于视频编解码层:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rfknjqFf-1642593855213)(vx_images/18190320226451.png)]

相关概念

H264编码标准中所遵循的理论依据个人理解成:参照一段时间内相邻的图像中,像素、亮度与色温的差别很小。所以当面对一段时间内图像我们没必要去对每一幅图像进行完整一帧的编码,而是可以选取这段时间的第一帧图像作为完整编码,而下一幅图像可以记录与第一帧完整编码图像像素、亮度与色温等的差别即可,以此类推循环下去。

  • 序列
    一段时间内图像变化不大的图像集我们就可以称之为一个序列。序列可以理解为有相同特点的一段数据。但是如果某个图像与之前的图像变换很大,很难参考之前的帧来生成新的帧,那么久结束删一个序列,开始下一段序列。重复上一序列的做法,生成新的一段序列。
  • 帧类型
    H264结构中,一个视频图像编码后的数据叫做一帧,一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由16x16的yuv数据组成。宏块作为H264编码的基本单位。
    在H264协议内定义了三种帧,分别是I帧、B帧与P帧。I帧就是一个完整的图像帧,而B、帧与P帧是不编码全部图像的帧。P帧是参考之前的I帧而生成的,而B帧是参考前后图像帧编码生成的。
  • GOP(画面组)
    GOP跟序列差不多意思,就是一段时间内变化不大的图像集。GOP结构一般有两个数字,如M=3,N=12。M指定I帧和P帧之间的距离,N指定两个I帧之间的距离。上面的M=3,N=12,GOP结构为:IBBPBBPBBPBBI。在一个GOP内I frame解码不依赖任何的其它帧,p frame解码则依赖前面的I frame或P frame,B frame解码依赖前最近的一个I frame或P frame 及其后最近的一个P frame。
  • IDR帧(关键帧)
    在编码解码中为了方便,将GOP中首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但I帧不一定是IDR帧;IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。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前面的帧

压缩方式

H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

帧内(Intraframe)压缩也称为空间压缩(Spatialcompression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多

帧间(Interframe)压缩也称为时间压缩。原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点,也即连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。

压缩步骤

  1. 分组,也就是将一系列变换不大的图像归为一个组,也就是一个序列,也可以叫GOP(画面组);
  2. 定义帧,将每组的图像帧归分为I帧、P帧和B帧三种类型;
  3. 预测帧, 以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
  4. 数据传输, 最后将I帧数据与预测的差值信息进行存储和传输。

分层结构

H264的主要目标是为了有高的视频压缩比和良好的网络亲和性,为了达成这两个目标,H264的解决方案是将系统框架分为两个层面,分别是视频编码层面(VCL)和网络抽象层面(NAL)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4jLdVDXe-1642593855216)(vx_images/436204720246617.png)]

VCL层是对核心算法引擎、块、宏块及片的语法级别的定义,负责有效表示视频数据的内容,最终输出编码后的数据比特串(SODB);
NAL层定义了片级以上的语法,负责以网络所要求的恰当方式格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。NAL层在SODB后面添加了结尾比特(用于字节对齐),打包成RBSP,然加上NAL头组成一个NALU(NAL Unit)。

码流结构

H264码流是由一个个的NAL单元组成,其中SPS、PPS、IDR和SLICE是NAL单元某一类型的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yHTUTIdu-1642593855217)(vx_images/230875620239286.png)]

NALU结构

实际的网络数据传输过程中H264的数据结构是以NALU进行传输的

[NALU] = [NALU Header]+[RBSP]
NALU头是用来标识后面RBSP是什么类型的数据,同时记录RBSP数据是否会被其他帧参考以及网络传输是否有错误,RBSP不单纯只保存I/B/P帧的数据编码信息,还可能包含传输序列参数集和图像参数集等信息

NALU头的组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEkQG2Sf-1642593855218)(vx_images/59150521235841.png)]

F(forbiden):禁止位,当禁止位值为1时表示语法错误;
NRI:参考级别,值越大,该NALU越重要
Type:NALU数据类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hrG3TDKw-1642593855219)(vx_images/516840721231595.png)]
NALU数据类型分为VCL和非VCL的NAL单元,SPS、SEI、PPS等非VCL的NAL参数对解码和显示视频都是很有用的。

  • SPS(序列参数集):SPS对如标识符、帧数以及参考帧数目、解码图像尺寸和帧场模式等 解码参数进行标识记录。
  • PPS(图像参数集):PPS对如熵编码类型、有效参考图像的数目和初始化等解码参数进行标志记录。
  • SEI(补充增强信息):这部分参数可作为H264的比特流数据而被传输,每一个SEI信息被封装成一个NAL单元。SEI对于解码器来说可能是有用的,但是对于基本的解码过程来说,并不是必须的。

参数集

参数集是携带解码参数的NAL单元,参数集对于正确解码是非常重要的,在一个有损耗的传输场景中,传输过程中比特列或包可能丢失或损坏,在这种网络环境下,参数集可以通过高质量的服务来发送,比如向前纠错机制或优先级机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UdXw6Wri-1642593855220)(vx_images/531482421249475.png)]

数据块类型??

  1. 头信息块,包括宏块类型,量化参数,运动矢量。这些信息是最重要的,因为离开他们,被的数据块种的码元都无法使用。该数据分块称为A类数据分块。
  2. 帧内编码信息数据块,称为B类数据分块。它包含帧内编码宏块类型,帧内编码系数。对应的slice来说,B类数据分块的可用性依赖于A类数据分块。和帧间编码信息数据块不通的是,帧内编码信息能防止进一步的偏差,因此比帧间编码信息更重要。
  3. 帧间编码信息数据块,称为C类数据分块。它包含帧间编码宏块类型,帧间编码系数。它通常是slice种最大的一部分。帧间编码信息数据块是不重要的一部分。它所包含的信息并不提供编解码器之间的同步。C类数据分块的可用性也依赖于A类数据分块,但于B类数据分块无关。
    以上三种数据块每种分割被单独的存放在一个NAL单元中,因此可以被单独传输

NALU 与片,宏块之间的联系

1帧(一幅图像) = 1~N个片(slice) //也可以说1到多个片为一个片组
1个片 = 1~N个宏块(Marcroblock)
1个宏块 = 16X16的YUV数据(原始视频采集数据)
宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zHfDN9ZV-1642593855221)(vx_images/228233221247079.png)]

其他

H.264/AVC标准对送到解码器的NAL单元顺序是有严格要求的,如果NAL单元的顺序是混乱的,必须将其重新依照规范组织后送入解码器,否则解码器不能够正确解码。

  1. 序列参数集NAL单元 必须在传送所有以此参数集为参考的其他NAL单元之前传送,不过允许这些NAL单元中间出现重复的序列参数集NAL单元。所谓重复的详细解释为:序列参数集NAL单元都有其专门的标识,如果两个序列参数集NAL单元的标识相同,就可以认为后一个只不过是前一个的拷贝,而非新的序列参数集。
  2. 图像参数集NAL单元 必须在所有以此参数集为参考的其他NAL单元之前传送,不过允许这些NAL单元中间出现重复的图像参数集NAL单元,这一点与上述的序列参数集NAL单元是相同

参考:

  1. https://blog.csdn.net/go_str/article/details/80340564
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值